Redis分布式锁怎么实现
这个问题分两种情况。第一种,业务能接受自动释放,那就让锁过期,业务自己承担并发风险。
第二种,业务必须保证原子性,那就用看门狗机制--锁快过期的时候自动续期。
Redission就是这么实现的。
Redission看门狗机制是怎么实现的?
Redission有个watchdog,默认每10秒检查一次,锁还在就续30秒。如果服务崩溃了,watchdog线程也挂了,锁也就自动过期,不会死锁。
如果redis是主从架构,主挂了,从还没同步锁怎么办?
这就是Relock红锁问题。红锁需要多个独立的Redis实例,比如,5个,获取锁需要3个以上成功才算拿到锁。这样即使主从切换,也不会丢失锁。
但红锁实现复杂,性能损耗大,大部分场景单节点Redis锁就够了。
总结:(1)互斥性。
同一把锁只能被一个客户端持有。用SETNX PX命令,SET和设置过期时间一步完成,保证原子性。如果拆成两步,SET成功了,但EXPIRE失败了,就死锁了。
(2)死锁避免。
获取锁的时候设置过期时间,防止服务崩溃锁不释放。但问题来了--过期时间设置多少?如果任务执行时间不稳定,设短了任务没跑完就自动释放,设长了服务崩溃要等很久才能自动释放。
解决方案:看门狗机制。Redission实现了一把带自动续期的锁。获取锁后启动一个后台线程,每隔10秒检查锁是否还在,如果在再续期30秒。如果客户端崩溃了,续期线程也跟着停了,锁自动过期。
(3)可重入。
同一个线程多次获取同一把锁会发生什么?如果不支持可重入,同一个线程第二次获取锁会失败。Redis分布式锁怎么支持可重入?用VALUE记录线程标识,重入的时候value加1,释放的时候value减1,减到0才真正删除。
主从切换:Redis主节点挂了,从节点还没同步锁的数据,新主节点已经接受新的锁的请求了,怎么办?
红锁的思路是不要信任单点,用多个独立的Redis实例。5个节点,获取锁需要3个以上成功才算拿到锁。这样即使一个节点挂了,最多只损失少数锁。但红锁实现复杂,需要多台机器,性能损耗也大。
大部分业务场景,用单节点Redis锁就够了,配合watchdog续期,主从切换的概率极低,丢了锁大不了重试。真可用要求特别高的场景采用红锁。
锁过期了任务还没跑完怎么办?答案不是唯一的,需要看业务场景,如果业务场景接受临时不一致,用过期时间就够了。需要强一致性的,用看门狗机制续期,或者拆分成细任务分批锁。性能优先的,用分段锁,把大任务拆成小任务。

浙公网安备 33010602011771号