Skip to content

分布式锁的深水区:Redisson 原理与脑裂问题解法

分布式锁的深水区:Redisson 原理与脑裂问题解法

Section titled “分布式锁的深水区:Redisson 原理与脑裂问题解法”

在单机应用里,用个 ReentrantLock 就能锁住线程。但在微服务里,当 10 台机器同时执行抢单、扣库存逻辑时,我们必须把锁放到一台大家都能看见的公共中间件上。这就是分布式锁

绝大多数开发者提到分布式锁,第一反应就是:“Redis 嘛,SETNX key value EX 10,搞定!”

如果你在 2026 年的架构评审会上这么说,大概率会被直接淘汰。因为纯手写的 SETNX 充满了致命的漏洞。

手写 Redis 分布式锁,通常死于以下三种死状:

死状一:过期时间无法把控(业务没跑完,锁被释放了)

Section titled “死状一:过期时间无法把控(业务没跑完,锁被释放了)”

你加了 EX 10(10 秒过期)。结果因为一次严重的 GC 停顿,或者数据库查询很慢,你的业务跑了 12 秒。 到了第 10 秒时,Redis 自动把锁删了。此时,第二台机器趁虚而入拿到了锁。两台机器同时操作同一笔订单,数据彻底污染。

紧接上面的剧情:第一台机器在第 12 秒终于跑完业务了,它去执行 DEL key 释放锁。但是,此时这个 key 其实是属于刚刚拿到锁的第二台机器的!第一台机器一通瞎操作,把别人的门给砸开了,导致第三台机器又闯了进来。

有人说,那我释放锁的时候先 GET 一下判断是不是我的锁,然后再 DEL。但这变成了两步操作。在多线程环境下,第一步判断通过,还没来得及删,如果发生线程切换,锁刚好过期,结果你依然可能误删别人的锁。

2. 业界标准:Redisson 与看门狗 (Watchdog)

Section titled “2. 业界标准:Redisson 与看门狗 (Watchdog)”

为了彻底解决这些问题,Java 圈的绝对标准变成了 Redisson 客户端。它是怎么做的呢?

Lua 脚本保驾护航(解决死状二和死状三)

Section titled “Lua 脚本保驾护航(解决死状二和死状三)”

在 Redisson 中,加锁和解锁的底层全是用 Lua 脚本交给 Redis 执行的。 Redis 在执行 Lua 脚本时,会将其视为一个原子操作。要么全成功,要么全失败,中途绝不允许其他命令插队。 同时,加锁时它会生成一个 UUID 作为 Value(标记这是哪个线程加的锁)。解锁的 Lua 脚本会先验证 UUID,匹配才执行删除,彻底杜绝了误删别人锁的可能。

核心黑科技:看门狗(Watchdog)机制(解决死状一)

Section titled “核心黑科技:看门狗(Watchdog)机制(解决死状一)”

如果你用 Redisson 加锁时不指定过期时间

RLock lock = redisson.getLock("my_lock");
// 不传 leaseTime,触发看门狗机制
lock.lock();

底层发生的故事极其精妙:

  1. Redisson 默认给你加一个 30 秒 超时的锁。
  2. 只要你的业务还在跑(当前线程持有锁),后台会有一个 Watchdog 守护线程(定时任务)
  3. 它每隔 30 / 3 = 10 秒,就向 Redis 发送一段续期 Lua 脚本,把这把锁的存活时间重新拨回到 30 秒(自动续命)!
  4. 当业务代码执行完 lock.unlock() 时,主动停止看门狗并删除锁。
  5. 神来之笔: 如果你的这台服务器突然断电宕机了(或者 JVM 崩溃),看门狗线程也死了,没法续命了。那么最多过 30 秒,这把锁就会被 Redis 自动释放,绝对不会造成死锁。

3. 终极拷问:Redlock 与集群脑裂 (Split-Brain)

Section titled “3. 终极拷问:Redlock 与集群脑裂 (Split-Brain)”

Redisson 这么完美,是不是天下无敌了?

有一天,你们公司的 Redis 从单机升级成了 Redis Cluster (主从哨兵架构)

  1. 你的应用向 Redis 主节点(Master)成功加上了一把锁。
  2. 主节点还没来得及把这把锁的数据同步(异步复制)给从节点(Slave),主节点网线被人拔了!
  3. 哨兵(Sentinel)发现主节点失联,立刻把从节点提拔成了新的主节点。
  4. 此时,另一个应用来抢锁。因为新的主节点上压根没有之前那把锁的记录,它加锁成功了

恭喜你,脑裂(Split-Brain)发生了! 同一时间,两台机器在两个脑子里都认为自己拿到了锁,并发惨案再次爆发。

Martin Kleppmann 的质疑与 ZooKeeper 的地位

Section titled “Martin Kleppmann 的质疑与 ZooKeeper 的地位”

分布式系统专家 Martin Kleppmann 曾对此提出严厉批评:Redis 的异步复制架构注定了它是一个 AP 系统(保证高可用),它根本不适合做绝对安全的强一致性分布式锁。

如果你是一个银行或者证券公司的核心交易系统,哪怕十万分之一的概率出现两把锁,都会造成真实的金钱损失。

这时候,你必须抛弃 Redis,转投 ZooKeeper (或 Etcd)。

ZooKeeper 的降维打击: ZooKeeper 采用的是基于 Paxos(ZAB 协议)的 CP 架构(保证强一致性)。 当你向 ZK 申请加锁(创建一个临时顺序节点)时,这个请求必须得到集群中过半数(多数派)节点的确认落盘,它才会返回成功给你。

这意味着:哪怕 Leader 节点挂了,新选举出来的 Leader 也一定包含了你刚才加锁的数据。在 ZooKeeper 的字典里,绝对不可能出现锁丢失导致脑裂的问题

在 2026 年的技术选型会议上:

  • 如果你的业务是“抢个优惠券”、“限制一个用户不能 1 秒内发两遍帖子”,使用 Redis + Redisson(AP架构)。极致的高性能,即便因为极端主从切换脑裂,导致多发了一张券,业务上打个补丁也就糊弄过去了。
  • 如果你的业务是“给千万级大客户做清算打款”,请老老实实引入 ZooKeeper(CP架构),并在数据库层面加上**悲观锁(FOR UPDATE)或乐观锁(版本号)**做最后的物理兜底。

没有包治百病的银弹,只有懂得权衡利弊的架构师。