Redis分布式锁实现原理


原文链接:https://mp.weixin.qq.com/s?__biz=MzU0OTk3ODQ3Ng==&mid=2247483893&idx=1&sn=32e7051116ab60e41f72e6c6e29876d9&chksm=fba6e9f6ccd160e0c9fa2ce4ea1051891482a95b1483a63d89d71b15b33afcdc1f2bec17c03c&mpshare=1&scene=23&srcid=1121Vlt0Mey0OD5eYWt8HPyB#rd

1.我们使用redis分布式锁,这里使用Redisson框架

RLock mylock = redisson.getLock("myLock");
mylock.lock();//加锁
mylock.unlock();//释放锁

 2.实现的原理图

  如图:客户端1想要加锁会选择一个节点(Redis Cluster(master))然后往redis发送一段lua脚本(lua脚本的作用:在执行一大段业务逻辑时,要保证其原子性)

  lua脚本:

    

// KEYS[1] 是传入的myLock ,ARGV[2] 代表的是加锁的客户端的ID,ARGV[1]:存活时间 默认30秒
"if (redis.call('exists' , KEYS[1]) == 0 ) then" + //判断KEYS[1]是否存在,不存在则执行
    "redis.call('hset',KEYS[1],ARGV[2],1); " + //存入对应的key,value值,最后的“1”代表加锁次数
    "redis.call('pexpire',KEYS[1],ARGV[1]); " + //锁的存活时间 默认30秒
    "return nil;" +
"end; "+ 
//重入锁机制
"if (redis.call('hexists',KEYS[1],ARGV[2]) ==1) then " +//如果锁:myLock和客户端ID存在则执行
    "redis.call('hincrby',KEYS[1],ARGV[2],1); "+ //加锁次数+1
    "redis.call('pexpire',KEYS[1],ARGV[1]); " + 
    "return nil;" +
"end; " + 
"return redis.call('pttl',KEYS[1]); " //其他人(客户端2)获取锁失败后会获取其锁(客户端1的锁)的存活时间,然后循环不断的尝试加锁

 3.watch dog (看门狗)自动延时机制

  一旦加锁成功,就会启动一个后台线程(watch dog)每10秒检测一次,如果客户端1仍然持有锁key,就会不断延长锁的存在时间

 4. 释放锁

  执行 mylock.unlock(),就会对myLock锁的加锁次数进行-1,当加锁次数为0时,就会就会执行 del myLock 删除锁