Redlock 想解决什么
Redlock 在 N 个相互独立的 Redis 主节点上用同一个键与随机令牌依次加锁,只有在多数节点(N/2+1)加锁成功且总耗时小于锁的 TTL 时才认为持锁成功;释放时对每个节点执行只删自己令牌的脚本。它的目标不是强一致,而是避免单实例故障导致锁服务整体不可用。
基本信息
| 适用 | Redis 2.6.12 及以上,多实例独立部署场景 |
|---|---|
| 加锁条件 | 成功节点数 ≥ N/2+1,且总耗时小于 TTL |
| 释放方式 | Lua 脚本比对令牌后删除,避免误删他人锁 |
| 前提 | 各节点时钟需 NTP 同步,网络延迟可控 |
加锁与释放流程
加锁与释放流程
# 对 5 个独立实例逐一加锁,成功数 >= 3 且总耗时小于 TTL 才算持锁成功
for h in 10.0.0.1 10.0.0.2 10.0.0.3 10.0.0.4 10.0.0.5; do
redis-cli -h $h -p 6379 SET lock:job 6f1d2c4e NX PX 10000 # 令牌必须每次随机
done
# 释放:只删除值等于自己令牌的键,避免误删新一轮持锁者的锁
# if redis.call('GET', KEYS[1]) == ARGV[1] then return redis.call('DEL', KEYS[1]) end
# 校验实际成功节点数,少于多数派要立刻释放已加上的锁争议观点对照
| 视角 | 核心论点 | 实践含义 |
|---|---|---|
| 可用性优先 | 单实例故障会让锁服务不可用,多实例多数派提升可用性 | 适合高并发互斥但可容忍极少误判的场景 |
| 强一致优先 | 依赖各节点时钟,GC 或网络暂停可让锁在实际过期后仍被使用 | 强一致场景应改用共识系统或数据库事务 |
| 折中做法 | 把 Redis 锁当高效互斥,而非绝对正确的锁 | 下游用唯一索引或 fencing token 拒绝过期持有者的写入 |
落地要点
- 节点要相互独立:同宿主、同交换机、同电源域都算不得独立
- 令牌每次加锁随机生成,释放前比对,避免误删他人的锁
- 锁外再设一层兜底:数据库唯一约束或版本号比较,防止过期写入
- 设置合理的 TTL 并配合续期机制,业务执行时间要小于 TTL
- 监控加锁成功率与耗时,多数派失败频繁说明网络或节点异常
把 Redlock 用在要求强一致的场景(例如资金扣减)风险很高:锁失效后的过期写入只有靠下游幂等或唯一约束才能拦住。
N 个 Redlock 节点若放在同一台宿主或同一台交换机下,多节点只是形式上的冗余,一挂全挂。