Redis 分布式锁的致命陷阱

53 阅读2分钟

使用 Redis 实现分布锁时,需要考虑哪些问题?

回答

1、锁的基本要求
  1. 对于锁的互斥性,可以借助 setnx 来保证

    因为这个操作本身就是一个原子性操作,并且结合Redis的单线程的机制,就可以保证互性。

    参考引用: Redis 的 SETNX 命令 为什么是原子性?

  2. Redis 是基于内存的,所以,他的性能也是很高的

    参考引用: Redis 为什么这么快?

  3. 对于可重入性

    1. 可以使用 setnx 来实现一个可重入锁

    2. 也可以使用 Redisson, Redisson 实现分布式锁

2、误解锁问题
  1. 建议:在解锁时,加一个判断。

unlock 一般在 finally 代码块里。那它是一定会执行的。

但,lock 可不一定会执行。

  1. 或者,使用 Redisson,Redisson 不存在这个问题。
3、锁的有效时间
  1. 核心矛盾锁超时时间设置业务执行时间的冲突

    • 代码执行时间 > 锁超时时间,结果会锁提前释放,否则会产生并发问题。

    • 典型场景:

      设置锁超时3秒 → 代码执行5秒 → 第3秒锁自动释放 → 其他线程获取锁 → 数据竞争

  2. 解决方案对比

    方案原理优点缺点适用场景
    延长超时时间设置更长的锁过期时间实现简单,快速规避问题并发度降低,锁竞争延迟非核心业务/低并发场景
    Watch Dog续期守护线程自动延长锁有效期动态调整,安全可靠实现复杂,需额外开发高并发/核心交易系统
  3. 锁超时时间设置原则

    • 基准值:业务平均执行时间的2倍 + 10%缓冲

    • 示例:业务平均耗时2秒 → 设置超时时间5秒

4、单点故障问题
  1. 引入集群模式,提升整个集群的可用性。

    参考引用: Redis 的集群模式

  2. RedLock 算法

    通过这种算法来保证在半数以上加锁成功才认为成功,

    这样就可以确保即使master挂了,新选出来的master也会有之前的加锁数据

    参考引用: RedLock 是什么?

5、网络分区问题
  • 理论上来说是有这个风险,但是,实际上来说发生的概率极低。
6、时间漂移问题
  1. 问题:导致有的redis实例提前解锁,这时,新的客户端可以拿到锁。

  2. 解决方案:

    RedLock 可以使用 NTP 等工具来同步不同机器之间的时间,

    从而避免时间漂移导致的问题。