使用 Redis 实现分布锁时,需要考虑哪些问题?
回答
1、锁的基本要求
-
对于锁的互斥性,可以借助 setnx 来保证
因为这个操作本身就是一个原子性操作,并且结合Redis的单线程的机制,就可以保证互性。
-
Redis 是基于内存的,所以,他的性能也是很高的。
参考引用: Redis 为什么这么快?
-
对于可重入性
-
可以使用 setnx 来实现一个可重入锁
-
也可以使用 Redisson, Redisson 实现分布式锁
-
2、误解锁问题
- 建议:在解锁时,加一个判断。
unlock 一般在 finally 代码块里。那它是一定会执行的。
但,lock 可不一定会执行。
- 或者,使用 Redisson,Redisson 不存在这个问题。
3、锁的有效时间
-
核心矛盾:锁超时时间设置与业务执行时间的冲突
-
代码执行时间 > 锁超时时间,结果会锁提前释放,否则会产生并发问题。
-
典型场景:
设置锁超时3秒 → 代码执行5秒 → 第3秒锁自动释放 → 其他线程获取锁 → 数据竞争
-
-
解决方案对比
方案 原理 优点 缺点 适用场景 延长超时时间 设置更长的锁过期时间 实现简单,快速规避问题 并发度降低,锁竞争延迟 非核心业务/低并发场景 Watch Dog续期 守护线程自动延长锁有效期 动态调整,安全可靠 实现复杂,需额外开发 高并发/核心交易系统 -
锁超时时间设置原则
-
基准值:业务平均执行时间的2倍 + 10%缓冲
-
示例:业务平均耗时2秒 → 设置超时时间5秒
-
4、单点故障问题
-
引入集群模式,提升整个集群的可用性。
参考引用: Redis 的集群模式
-
RedLock算法通过这种算法来保证在半数以上加锁成功才认为成功,
这样就可以确保即使master挂了,新选出来的master也会有之前的加锁数据
参考引用: RedLock 是什么?
5、网络分区问题
- 理论上来说是有这个风险,但是,实际上来说发生的概率极低。
6、时间漂移问题
-
问题:导致有的redis实例提前解锁,这时,新的客户端可以拿到锁。
-
解决方案:
RedLock 可以使用 NTP 等工具来同步不同机器之间的时间,
从而避免时间漂移导致的问题。