一、为什么需要 Redlock?
背景问题:
在实际生产环境中,单个 Redis 实例可能存在以下风险:
风险 | 说明 |
---|---|
单点故障(SPOF) | Redis 宕机会导致锁失效 |
主从复制延迟 | 使用哨兵或集群,主从之间同步是异步的,可能导致锁误删 |
网络分区问题 | 节点彼此之间通信中断,客户端可能和不同 Redis 发生交互,导致锁争抢错误 |
所以问题是:
如何在多 Redis 节点中安全地加锁,同时避免网络和节点不一致导致的锁"幻觉"?
于是 Redis 作者 antirez(Salvatore Sanfilippo)提出了 Redlock 算法。
二、Redlock 的设计目标
保证即使在 Redis 节点部分失效、网络延迟等问题下,也能安全地获得分布式锁,并确保"只有一个客户端获得锁"。
三、Redlock 的核心思想
Redlock 使用多个相互独立的 Redis 实例(建议 5 个),算法流程如下:
✅ 加锁流程(五步):
-
获取当前时间戳
T1
(毫秒) -
使用相同的
key
和value
向 多个 Redis 节点顺序执行加锁操作,命令:SET lock_key value NX PX 30000
-
尝试在 大多数节点 上加锁成功(比如 5 个节点中 ≥3 个成功)
-
计算总耗时
T2 - T1
,必须小于锁的过期时间(比如 30000ms) -
若满足以上条件,则加锁成功,否则失败并回滚(解掉已经加上的锁)
✅ 只有同时满足"多数节点成功 + 时间窗口有效",才认为锁真正成功。
四、Redlock 加锁成功的示意图
Client A Redis-1 Redis-2 Redis-3 Redis-4 Redis-5
|-----------------> SET NX PX (成功)
|-----------------------------> SET NX PX (成功)
|-------------------------------------> SET NX PX (失败)
|-------------------------> SET NX PX (成功)
|-----------------------------------------------> SET NX PX (成功)
✅ 成功节点 = 4 >= 3
⏱ 加锁耗时 = 30ms < 30000ms
🔐=> 加锁成功!
五、Redlock 的释放锁逻辑
与单节点 Redis 锁相同,必须使用 Lua 脚本确保只删除自己的锁,否则可能删错别人设置的锁。
客户端应在每个实例上执行以下逻辑:
if redis.call("get", KEYS[1]) == ARGV[1] then
return redis.call("del", KEYS[1])
else
return 0
end
六、Redlock 的优点
优点 | 说明 |
---|---|
高容错 | 允许部分 Redis 节点故障 |
避免主从延迟风险 | 不依赖某个主节点,多个节点投票机制更健壮 |
强一致性更近一步 | 多节点协调提升了锁的可靠性 |
官方推荐方案 | 来自 Redis 原作者,适合追求安全性的分布式场景 |
七、Redlock 的缺点 & 争议点
虽然 Redlock 设计理念优秀,但在业界也有一定争议:
-
复杂性高:需要多个 Redis 实例维护、同步、多点操作、时钟精度问题
-
实际并不绝对安全:在极端网络分区场景下仍可能导致脑裂
-
Redisson 中实现的是"改良版":引入了"看门狗"机制自动续约
参考论文:《How to do distributed locking》(Martin Kleppmann)
八、Redlock 实践建议
-
使用 Redis 5 个独立节点(物理或逻辑隔离)
-
设置合理过期时间(避免锁误释放)
-
使用
UUID
作为锁值,防止误删他人锁 -
使用 Lua 脚本释放锁
-
可以使用
Redisson
作为客户端库,它对 Redlock 做了良好封装
九、Redlock vs 普通 Redis 分布式锁对比
项目 | 单节点 Redis 锁 | Redlock |
---|---|---|
节点数量 | 1 | ≥ 3(推荐5) |
可用性 | 容易单点故障 | 容错性强 |
一致性 | 较弱(主从问题) | 更强 |
复杂性 | 简单 | 较高 |
实现方式 | SET NX PX | 多节点投票、时间窗口 |
十、总结一句话
Redlock 是一种提升 Redis 分布式锁一致性和容错性的算法,通过多个独立 Redis 实例投票确认,降低因单节点故障或主从延迟带来的锁安全隐患。