Redisson 加锁原理
一、分布式加锁过程
RLock lock = redissonClient.getLock(REDISSON_DISTRIBUTE_KEY);
lock.lock();
wireshark抓包可以看见:
*6 $4 EVAL $336 if (redis.call('exists', KEYS[1]) == 0) then redis.call('hset', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; if (redis.call('hexists', KEYS[1], ARGV[2]) == 1) then redis.call('hincrby', KEYS[1], ARGV[2], 1); redis.call('pexpire', KEYS[1], ARGV[1]); return nil; end; return redis.call('pttl', KEYS[1]); $1 1 $30 cache.redisson.distribute.lock $5 30000 $40 b56fb34c-e1b7-400f-a635-ad6881f75c7b:110
整理后,如下:
// 如果key不存在,则调用hashset去设置,并设置过期时间
if (redis.call('exists', cache.redisson.distribute.lock) == 0) then redis.call('hset', cache.redisson.distribute.lock, b56fb34c-e1b7-400f-a635-ad6881f75c7b:110, 1); redis.call('pexpire', cache.redisson.distribute.lock,30000); return nil; end;
//key已经存在的情况下,直接incrby,然后设置过期时间 if (redis.call('hexists', cache.redisson.distribute.lock, b56fb34c-e1b7-400f-a635-ad6881f75c7b:110) == 1) then redis.call('hincrby', cache.redisson.distribute.lock, b56fb34c-e1b7-400f-a635-ad6881f75c7b:110, 1); redis.call('pexpire', cache.redisson.distribute.lock, 30000); return nil; end; return redis.call('pttl', cache.redisson.distribute.lock);
二、redisson 解锁过程
整理后,脚本如下:
if (redis.call('hexists', cache.redisson.distribute.lock, e16193b0-e25c-4563-bc6e-19cc88d6112a:105) == 0) then return nil; end;
// -1操作 local counter = redis.call('hincrby', cache.redisson.distribute.lock, e16193b0-e25c-4563-bc6e-19cc88d6112a:105, -1); if (counter > 0) then
// 延长过期时间 redis.call('pexpire', cache.redisson.distribute.lock, 30000); return 0; else
// 删除分布式锁的key,发布消息 redis.call('del', cache.redisson.distribute.lock); redis.call('publish', redisson_lock__channel:{cache.redisson.distribute.lock}, 0); return 1; end; return nil;
https://my.oschina.net/u/2369201/blog/1573730
三、续期原理
可参考:https://juejin.im/post/5d122f516fb9a07ed911d08c
验证时,如下图,在过了20s后,(程序在sleep),开始续期:
看看续期包的内容:
可以看到,续了30s。然后因为我们睡眠了1分钟,所以接下来又触发了续期: