Redis实现分布式锁

基础版

直接SETNX lock 1就行。但有个问题A设置完,假设A的业务流程卡了或者直接宕机了。其他业务无法获取到锁。

设置过期时间

SET lock 1 nx ex 3,设置一下过期时间就行。但是还存在一个问题,这个对于过期时间设置需要比较高超的技巧。假设设置的没业务执行时间长,或者业务执行时候网络延迟、GC卡顿了。那么A没等主动释放锁呢,先过期了,B就会获取到锁,结果A这时候执行完了给人家B的锁释放了。这肯定不行

设置owner

SET lock tju nx ex 3,然后释放锁的时候要先比对一下这个锁是不是我的。遇到上面的情况发现不是自己的,那么证明已经过期了,就不释放了。

原子化

其实比对再释放这两操作不是原子的,可能比对发现是自己的,然后DEL时候已经不是自己的了。所以可以把这两步合成一个Lua脚本里,执行脚本的命令是一个原子化操作。

Lua脚本

其实redis也有原生的multi事务来保证原子性,但是假设出错不会中断或回滚,它会继续执行。Lua可以保证事务失败就立刻中断后续执行,但是之前执行了的部分没法挽回,所以Lua只是保证了不被打断的这个原子性

可靠性

其实上面的那个方案已经基本满足大多数场景了。但是可靠性没有保证,就是你得容灾。

主从

主节点寄了,从节点顶上。这个Redis有哨兵模式可以帮忙解决,不用人工介入。
在一定程度上容灾了,但是有问题,数据同步是有延迟的,A在主节点获得锁,这个信息没来得及同步到从节点,主节点就寄了,B在从节点上同样获取了这个锁。

多机部署

这个Redis的Redlock就是这个方式,通过设置奇数个Redis主节点(实际上就是集群模式,每个Redis节点下面还可以用主从再套娃)来容灾。
假设是5个,每次都会向所有5个Redis申请加锁,超过半数返回成功,也就是3个才会获得锁。反之失败,要向所有Redis节点发送释放锁命令(因为可能是获得成功的,但是网络原因让其返回失败了)。使用完后向所有节点发送解锁请求。

这样即使挂了2台机器,还是可以正常运行,给运维提供了处理时间

但总之没有绝对可靠的方式

因为本来网络就不是完全可靠的,关键业务肯定还是要靠幂等兜底的。Redlock的集群模式可以尽可能降低出错概率(但开销比较大)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值