Redis用setnx+expire实现分布式锁存在什么隐患,如何改进?

用Redis实现分布式锁,2.6.12之前版本方案:setnx加锁,del释放锁,如果锁没释放,设置过期时间,到了时间,del释放锁。但是,这会存在一些问题。

  1. setnx和expire不是原子操作一旦redis宕机,expire没有设置成功,锁就无法释放。只有一个请求的setnx可以成功,任何一个请求的expire都可以成功。请求比较密集,过期时间一直刷新,导致锁一直有效。
  2. 超时后,释放其他线程的锁。在线程A执行过程中,锁已释放,A持有。线程B获取锁,线程A执行完,释放锁,A误删B的锁。
  3. 多个线程并发获取锁、释放锁。同一时间有线程A、B在访问同一代码块。

对于上面的隐患,Redis已改善。下面,我们针对隐患逐一改善。

  1. Redis2.6.12以上版本,可以用set获取锁。set可以实现setnx和expire,这个是原子操作。
  2. Lua释放锁。Lua是原子操作。
  3. 让获取锁的线程开启一个守护线程,给线程还没执行完,又快要过期的锁续航。大概是这样的,线程A还没执行完,守护线程每当快过期时,延时expire时间。当线程A执行完,显示关闭守护线程。如果中间宕机,锁超过超时,守护线程也不在了,自动释放锁。

猜你喜欢

转载自www.cnblogs.com/ivy-xu/p/12613267.html