非常好的问题 👍
Redis 实现分布式锁是后端高并发与分布式系统中的核心话题。
目前常见的 Redis 分布式锁实现方案主要有 7 种,它们在可靠性、性能、容错性上各有差异。
下面我帮你系统整理——
🚀 Redis 实现分布式锁的 7 种方案(从简单到高级)
编号 | 实现方案 | 是否推荐 | 难度 | 特点 |
---|---|---|---|---|
① | SET NX + EX (单实例) | ✅ 推荐(基础场景) | ⭐ | 简单高效,最常见的方式 |
② | SETNX + EXPIRE (分两步) | ❌ 不推荐 | ⭐ | 存在原子性问题,容易死锁 |
③ | Lua 脚本实现加锁与解锁 | ✅ 推荐 | ⭐⭐ | 保证原子性,安全可靠 |
④ | Redisson 分布式锁 | ✅✅ 强烈推荐 | ⭐⭐⭐ | 官方成熟方案,支持锁续期与公平锁 |
⑤ | RedLock(多节点锁) | ⚠️ 谨慎使用 | ⭐⭐⭐⭐ | 高容错,理想方案但实现复杂 |
⑥ | 基于 Pub/Sub 的锁(订阅通知解锁) | ⚠️ 特殊场景可用 | ⭐⭐⭐ | 可避免轮询,但复杂度高 |
⑦ | 基于 Zookeeper/Etcd + Redis 混合锁 | ⚙️ 实验性方案 | ⭐⭐⭐⭐ | 兼顾一致性与高可用,成本高 |
🧩 一、SET NX PX
(最经典的实现)
命令:
SET lock_key unique_value NX EX 30
- NX:只在键不存在时设置成功
- EX 30:30 秒过期自动释放
- unique_value:防止误删他人锁(一般用 UUID)
解锁操作:
if redis.call("get", KEYS[1]) == ARGV[1] then
return redis.call("del", KEYS[1])
else
return 0
end
✅ 优点:
- 简洁、性能高
- 单节点即可使用
- 自动过期防止死锁
⚠️ 缺点:
- 单实例不具备容错能力(Redis宕机锁丢失)
🧩 二、SETNX
+ EXPIRE
(老式写法)
SETNX lock_key unique_value
EXPIRE lock_key 30
❌ 问题:
两条命令不是原子操作,如果进程在 SETNX
后宕机,锁永不过期,造成死锁。
👉 已被 SET NX EX
完全取代。
🧩 三、Lua脚本(保证原子性)
Lua 可将 加锁 / 解锁 / 续期 整合成一个原子操作。
加锁 Lua 脚本示例:
if redis.call("setnx", KEYS[1], ARGV[1]) == 1 then
redis.call("expire", KEYS[1], ARGV[2])
return 1
else
return 0
end
解锁 Lua 脚本(防止误删)同上第一种。
✅ 优点:
- 原子性强,无竞争问题
- 可封装复杂逻辑
🧩 四、Redisson(Java官方最完善实现)
Redisson 是 Redis 官方推荐的分布式锁客户端。
核心特性:
- 自动续期机制(看门狗机制,默认30秒续期)
- 可重入锁、公平锁、读写锁
- 支持锁超时与安全释放
示例代码:
RLock lock = redissonClient.getLock("order_lock");
lock.lock(); // 自动续期
try {
// 业务逻辑
} finally {
lock.unlock();
}
✅ 优点:
- 企业级稳定方案
- 适合微服务 / 高并发场景
- 避免死锁与误删
⚠️ 缺点:
- 依赖 Redisson 客户端
- 内部逻辑复杂(但透明)
🧩 五、RedLock(Redis 官方多节点算法)
RedLock 是 Redis 作者 antirez 提出的分布式锁算法。
核心思想:
- 在 5 个 Redis 实例中获取锁
- 超过半数(≥3)成功即视为加锁成功
- 使用相同的
unique_value
标识客户端
加锁流程:
- 客户端生成唯一 UUID
- 顺序尝试获取锁(带超时)
- 超过半数成功 → 加锁成功
- 否则 → 释放已获取的锁,重试
✅ 优点:
- 高可靠,不依赖单节点
- 容忍部分节点宕机
⚠️ 缺点:
- 实现复杂
- 延迟高、时钟漂移风险
- Redis 官方后来认为该算法仅理论安全,不推荐生产使用
🧩 六、Pub/Sub 通知锁
使用 Redis 的发布订阅机制,当锁释放时通知其他等待者。
流程:
- 客户端尝试加锁失败 → 订阅
unlock_channel
- 释放锁时 → 发布通知
- 等待者收到通知 → 再尝试加锁
✅ 优点:
- 避免轮询(节省CPU)
⚠️ 缺点:
- 实现复杂,不够通用
- 可能存在“假唤醒”或通知丢失问题
🧩 七、混合方案(Zookeeper/Etcd + Redis)
部分系统结合 Redis + Zookeeper:
- Redis 提供高性能访问
- Zookeeper 负责一致性与可靠释放
✅ 优点:
- 兼顾性能与强一致性
- 可防止 Redis 崩溃造成的锁丢失
⚠️ 缺点:
- 架构复杂,成本高
- 一般用于金融级系统(如支付网关)
📘 总结推荐
场景 | 推荐方案 | 说明 |
---|---|---|
单机、低风险 | SET NX EX + Lua | 简单高效 |
分布式系统(Java) | Redisson | 自动续期、最成熟 |
多节点容灾 | RedLock(谨慎)或 混合锁 | 仅在强一致性要求高时 |
超高并发、消息队列协作 | Pub/Sub 或 Stream 通知锁 | 特殊业务可用 |
✅ 建议实践方案(通用推荐)
👉 加锁
SET lock_key unique_value NX PX 30000
👉 解锁(Lua脚本)
if redis.call("get", KEYS[1]) == ARGV[1] then
return redis.call("del", KEYS[1])
else
return 0
end
👉 续期机制(可选)
由业务逻辑或定时器在过期前重新 PEXPIRE
锁。
发表回复