Redis-分布式锁

Redis分布式锁的原理、问题及解决方案:

Redis分布式锁是通过 SET lock $uuid EX 20 NX 方法来进行加锁

Redis 2.6.12 之后,Redis 扩展了 SET 命令的参数,把 NX/EX 集成到了 SET 命令中,用这一条命令就可以了

EX是设置存活时间,NX是只有没有这个key才进行操作

加锁后还需要一个守护线程,去定时延长这个key的存活时间,不然会存在代码没有执行完毕,锁释放了的情况

在Redisson中,被称为看门狗机制

之所以把锁的Value设置为UUID(唯一标识),是为了防止其他线程将锁释放

所以在释放锁的时候,得先判断锁是不是自己的锁(唯一标识一不一致),是自己的锁才释放
这里又会有一个问题,判断和解锁存在原子性问题,可能存在,判断的时候是自己的锁,释放的时候不是自己的锁了

这个我们可以通过编写Lua脚本,来规避这个问题,因为Redis是单线程的

不过即使这样,在主从集群+哨兵模式下,还是会存在问题

Redis主从集群+哨兵模式的原理、问题及解决方案:

主从集群是通过主从复制进行同步数据的,主从复制是一个异步请求

当客户端在主库中加锁后,主库宕机了,最新数据还没同步到从库上,这个时候哨兵模式会实现故障自动切换,将从库被提为主库,继续提供服务,但是当前主库的锁就丢失了,还是会引起安全性问题

这个问题是因为主库宕机时产生的,所以官方的解决方案是使用RedLock解决这个问题

RedLock的原理、问题:

RedLock是部署多台Redis实例,每台Redis都是相互独立的主库,假设部署了5台Redis,分别为A、B、C、D、E

当客户端发起加锁请求之前,先记录当前的时间T1

然后再向各个Redis发起加锁请求,每次请求设置一个过期时间(这个时间要远小于锁的有效时间),一个一个Redis请求

如果加锁成功的Redis实例有大多数(大于等于3)都加锁成功时,记录当前时间T2,当T2-T1<锁的过期时间时,视为加锁成功,否则视为加锁失败

这里判断时间的目的是:为了防止当A加锁成功后,请求B时,发生了网络延迟或者进程GC,导致请求B的时间比锁的过期时间还长,致使A的锁自动释放了,另外一条线程又来拿A的锁是可以正常拿到的,之前那个线程也认为自己拿到了A的锁,从而出现的问题

加锁失败,或者加锁成功处理完业务后,需要对所有的Redis实例进行释放锁处理

不过即使这样处理,还是会存在,当拿到锁后,修改共享资源时,出现NPC,还是会出现安全性问题
N:Network Delay,网络延迟
P:Process Pause,进程暂停(GC)
C:Clock Drift,时钟漂移

总结:

1.分布式锁不是100%安全的
2.在修改敏感数据时,需要资源层进行兜底,例如乐观锁

参考资料

https://cloud.tencent.com/developer/inventory/52658/article/2332108

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值