Redis:Redisson看门狗续锁实现分布式锁的原理,及如何避坑

文章介绍了Redis在微服务场景下用于实现分布式锁的机制,强调了互斥性、锁过期时间和可重入性等关键要求。RedissonLock的tryLock和unlock方法使用lua脚本来保证原子性操作。同时,文章提到了单实例锁的问题,如数据丢失风险,并推荐使用红锁解决集群锁问题,以及提出了业务幂等性作为兜底策略。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

简介

在微服务场景下,为了防止多个进程及线程并发访问共享资源,如支付、下单等操作,会引入分布式锁来保证业务的并发安全。

Redis实现分布式的要求

1、互斥性;

防止多个进程及线程并发访问共享资源,使得资源串行访问操作。

2、设置锁过期时间;

为了防止锁悬挂,因为服务宕机,锁不释放问题,其它请求就无法获取锁。

3、自动续锁超时时间;

防止业务超时,超过锁过期时间自动释放,打破互斥性。

4、多条指令需要原子性;

lua脚本实现多个指令的加锁、解锁及续锁的原子性。

5、可重入性;

使用线程ID信息来保证同一线程请求锁的可重入性。

6、锁误删:自己把别人持有的锁删了;

多个客户端释放锁,如何防止自己删别人的或者别人删自己申请的锁。
获取锁之前,生成全局唯一id,判断是否是自己的id来避免。

7、锁等待:发布订阅机制通知等待锁的线程;

Redisson看门狗续锁实现分布式锁

以RedissonLock为例来分析

org.redisson.RedissonLock#tryLock()org.redisson.RedissonLock#unlock的实现。

tryLock方法调用分析:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

当锁超时时间为-1时,而且获取锁成功时,会启动看门狗定时任务自动续锁:

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

每次续锁都要判断锁是否已经被释放,如果锁续期成功,自己再次调度自己,持续续锁操作。
为了保证原子性,用lua实现的原子性加锁操作:

lua加锁流程:

在这里插入图片描述

获取锁或锁重入,lua返回nil即Java的NULL值,如果获取锁失败,则返回锁的ttl时间。

根据返回值编码的设置:
在这里插入图片描述

RedisStrictCommand<Boolean> EVAL_NULL_BOOLEAN = new RedisStrictCommand<Boolean>("EVAL", new BooleanNullReplayConvertor());

返回NULL代码获取锁成功,后续开启续锁流程,否则返回false,表示获取锁失败。

unlock方法调用分析:

在这里插入图片描述

在这里插入图片描述

为了保证原子性,用lua实现的原子性释放锁操作:

释放锁流程:

在这里插入图片描述

发布订阅机制是为了通知调用org.redisson.RedissonLock#lock()方法等待锁的线程。

以上我们注意到,线程id信息携带了一个UUID随机数,是为了防止集群环境下,线程ID相同导致误删问题。

为了保证原子性,用lua实现的原子性续锁操作:
在这里插入图片描述

单实例锁VS集群锁

上面介绍的锁实现只能使用于单Redis实例,不支持Redis集群。并且如果锁所在的Redis实例挂掉了之后,采用哨兵模式进行主备切换。但由于Redis的主从复制(replication)是异步的,这可能会出现在数据同步过程中,master宕机,slave来不及同步数据就被选为master,从而数据丢失。

Redis的作者提供了红锁来实现集群锁,算法思想:https://redis.io/docs/reference/patterns/distributed-locks/;

Redisson看门狗续锁实现分布式锁-避坑

1、不要传递自定义锁超时时间,否则不会续锁;
2、加锁和释放锁要在同一个线程,否则影响可重入性逻辑判断,导致续锁、释放锁失败;
3、单实例宕机,主从切换问题导致锁丢失;

做了主从,或者使用了哨兵模式,基于redis的分布式锁的功能,就会出现问题。

如何避免:

1、使用红锁解决,当然红锁的实现也有自己的问题;
2、使用锁的Redis实例单独分配且业务隔离,尽量保证不宕机,监控此实例,及时响应报警处理;
3、业务实现幂等来兜底;

小结

在这里插入图片描述

Redis学习资料:

redis: https://url97.ctfile.com/d/36436597-51573286-ccffc3?p=1988 (访问密码:1988)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值