Day XX 分布式锁
单个服务加锁:
使用 synchronized 或者 lock
分布式架构:
多个服务同时运行时,需要对这些服务进行加锁。
Redis 分布式锁原理
使用到的命令
setnx 加锁
expire 设置锁过期时间
使用 set 同时设置过期时间
set lock "1234" EX 100NX
使用 lua 脚本
eval "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}" 2 key1 key2 first second
原理分析
-
key 不存在时创建,并设置 value 和过期时间,返回值为1;成功获得锁;
-
如果 key 存在时直接返回0,则表示抢锁失败
-
蚩尤蓑的线程释放锁时,手动删除 key;或者过期时间到,key 自动解除
Jedis 分布式锁实现
加锁
set key value [EX seconds] [PX milliseconds] [NX|XX]
锁过期问题
问题描述:业务操作时间超过锁过期时间。业务会在无锁状态下运行。
解决方式:
-
乐观锁
-
watch dog 自动延期
乐观锁
增加版本号,但是需要调整业务逻辑与之配合。所以会产生代码入侵。
watch dog
不会侵入业务代码,redisson采用此方法。
客户端一旦加锁成功,就会启动一个 watch dog, 每隔一段时间会检查一下,如果客户端还持有锁,那么就会不断延长锁 key 的生存时间。
Redisson 分布式锁
Redisson 是基于 Netty 的 Redis 客户端。不但能操作原生的 Redis 数据,还可为使用者听一系列具有分布式特征的常用工具类。实现了分布锁。
Redisson 锁结构
key:锁的名字
字段:UUID + threadID
值:表示重入的次数
Redisson 加锁原理
加锁
判断是否存在 “DISLOCK” ;若没有,则设置 UUID:1=1 并设置过期时间
锁重入
key 和字段都存在,锁重入;执行名 incrby UUID:1 1
互斥锁
另外的客户端访问资源,判断有 key 但没有字段;返回过期时间,客户端2自旋等待
释放锁
判断 key 是否存在;如果不存在,返回 nil;如果存在,使用 hincrby -1;
若 counter >0 则返回0
若 counter <= 0 则删除 key;使用 publish 广播锁释放消息
watchdog 自动延期
当加锁成功后,同事开启守护线程。默认有效期为30s,每隔10s会给锁续期到30s
分段锁
将锁分为多个段。以空间换时间。
分布式锁原理