Redis如何实现分布式锁

 参考: (9条消息) 如何用Redis实现分布式锁_redis分布式锁_GeorgiaStar的博客-CSDN博客

(9条消息) Redis实现分布式锁_kongmin_123的博客-CSDN博客

步骤:1.加锁;2.执行业务逻辑;3.释放锁

问题:

一、出现死锁:1.业务逻辑出现异常,没有及时释放锁;2.线程挂了,没机会释放锁

解决办法:设置过期时间

可能出现:

1. SETNX执行成功,执行EXPIRE时由于网络问题,执行失败

2. SETNX执行成功,Redis异常宕机,EXPIRE没有机会执行

3. SETNX执行成功,客户端异常崩溃,EXPIRE没有机会执行

解决办法:使用set,在redis2.6.12以上版本set增加了可选参数,例: SET lock_key 1 EX 10 NX

二、由于锁过期,释放了别人的锁:

1. 客户端1加锁成功,开始操作共享资源

2. 客户端1操作共享资源耗时太久,超过了锁的过期时间,锁失效(锁被自动释放)

3. 客户端2加锁成功,开始操作共享资源

4. 客户端1操作共享资源完成,在finally块中手动释放锁,但此时它释放的是客户端2的锁。

解决办法:加锁时将一个只有自己知道的唯一标识作为value设置

可能出现:由于释放锁时需要进行get+del两个操作,出现原子性问题

1. 客户端1执行GET,判断锁是自己的

2. 客户端2执行了SET命令,强制获取到锁(虽然发生概念很低,但要严谨考虑锁的安全性)

3. 客户端1执行DEL,却释放了客户端2的锁

解决办法:使用Lua脚本

三、锁过期

解决办法:加锁时,先设置一个预估的过期时间,然后开启一个守护线程,定时去检测这个锁的失效时间,如果锁快要过期了,操作共享资源还未完成,那么就自动对锁进行续期,重新设置过期时间。

已有方案: Redisson。它可以像操作本地锁一样操作分布式锁。客户端一旦加锁成功,就会启动一个watch dog看门狗线程,它是一个后台线程,会每隔一段时间(这段时间的长度与设置的锁的过期时间有关)检查一下,如果检查时客户端还持有锁key(也就是说还在操作共享资源),那么就会延长锁key的生存时间。如果客户端在加锁成功后就宕机了呢?宕机了那么看门狗任务就不存在了,也就无法为锁续期了,锁到期自动失效。

四、Redis部署方式对锁的影响

Redis发展到现在,几种常见的部署架构有:

1.单机模式;3.主从模式;3.哨兵(sentinel)模式;4.集群模式;

我们使用Redis时,一般会采用主从集群+哨兵的模式部署,哨兵的作用就是监测redis节点的运行状态。普通的主从模式,当master崩溃时,需要手动切换让slave成为master,使用主从+哨兵结合的好处在于,当master异常宕机时,哨兵可以实现故障自动切换,把slave提升为新的master,继续提供服务,以此保证可用性。

可能出现:锁丢失

1. 客户端1在master上执行SET命令,加锁成功

2. 此时,master异常宕机,SET命令还未同步到slave上(主从复制是异步的)

3. 哨兵将slave提升为新的master,但这个锁在新的master上丢失了,导致客户端2来加锁成功了,两个客户端共同操作共享资源

解决方法:集群模式+Redlock实现高可靠的分布式锁(Redlock算法的实现要求Redis采用集群部署模式,无哨兵节点,需要有N个独立的Redis实例(官方推荐至少5个实例))

Redlock算法的基本思路:让客户端和多个独立的Redis实例依次请求加锁,如果客户端能够和半数以上的实例成功地完成加锁操作,那么我们就认为,客户端成功地获得分布式锁了,否则加锁失败。

加锁分三步:

1.客户端获取当前时间。

2.客户端按顺序依次向N个Redis实例执行加锁操作。

3.一旦客户端完成了和所有Redis实例的加锁操作,客户端就要计算整个加锁过程的总耗时。(客户端只有在满足两个条件时,才能认为是加锁成功,条件一是客户端从超过半数(大于等于 N/2+1)的Redis实例上成功获取到了锁;条件二是客户端获取锁的总耗时没有超过锁的有效时间。)

释放锁时客户端就要向所有Redis节点发起释放锁的操作。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值