Redisson分布式锁初步了解
定义
分布式锁:在分布式场景下,多台机器竞争一项资源去加锁。
常用的分布式锁:数据库、zookeeper、Redis。
版本一
Redis的加锁命令:setnx(set if not exist),例子:setnx key value。
这个命令会使Redis中如果不存在key就会创建值为value的key并返回1,存在的话就返回0。
结论:setnx命令是互斥的,基本能达到加锁的目的。
版本二
版本一有个缺陷:机器A上锁后宕机了,锁不会自动释放,那机器B永远拿不到锁。
解决一:把setnx key value 和 expire key overtime,两个命令写到一个lua脚本执行,保证原子性
解决二:set key value nx ex overtime,ex过期时间单位是秒
结论:解决了版本一永远不释放的问题
版本三
版本二的缺陷一:过期时间的颗粒度怎么设置,设置过长影响效率,设置过短任务还没执行完
版本二的缺陷二:如果锁提前释放,会导致多线程并发执行,执行完后可能会释放对方的锁
解决一:看门狗WatchDog,通过定时任务,默认过期时间30秒,则每隔10秒检查,是否要延长过期时间
解决二:UUID和线程ID作为value来进行身份识别
源码初看
看的是redisson-3.15.6.jar包中的代码
- 加锁、解锁都是通过执行lua脚本来实现
- 等待锁是通过发布订阅功能来实现,避免自旋对资源的消耗
- 加锁、解锁使用的数据类型是Hash表,其中key为UUID+线程ID,value为加锁次数(可重入锁)
- 看门狗用的是TimerTask定时任务来实现
总结
Java连接Reids的常用客户端有Jedis、Lettuce、Redisson,如果想要功能多方案全那就选Redisson,另外它还实现了公平锁、读写锁、红锁、联锁等功能,对于普通项目的常规使用完全够了。