Redis 是高性能的内存数据库,它的 原子操作 和 过期机制 特别适合实现分布式锁。在分布式系统中,合理的 Redis 分布式锁可以保证多个服务对共享资源的互斥访问。下面总结 7 种常见 Redis 分布式锁实现方案,并分析优缺点。
1️⃣ SETNX + EXPIRE(最基础方案)
实现思路:
- 使用
SETNX
(Set if Not eXists)设置锁 key,如果 key 不存在则成功获取锁。 - 再设置
EXPIRE
设置锁过期时间,避免死锁。 - 释放锁时使用
DEL
删除 key。
SETNX lock_key request_id
EXPIRE lock_key 10 -- 设置10秒过期
-- 释放锁
if redis.get(lock_key) == request_id then
DEL lock_key
end
优点:
- 实现简单,原子性较高。
缺点:
SETNX
与EXPIRE
不是原子操作,可能在服务崩溃时造成死锁。- 锁释放存在误删风险(必须用唯一标识 request_id 防止误删)。
2️⃣ SET NX PX + 原子操作(推荐方案)
实现思路:
- Redis 2.6.12+ 支持
SET key value NX PX milliseconds
:NX
:不存在时设置PX
:设置过期时间
- 该命令是原子操作,同时完成锁和过期时间设置。
SET lock_key request_id NX PX 10000
- 释放锁依然使用 Lua 脚本保证原子性:
if redis.get(KEYS[1]) == ARGV[1] then
return redis.del(KEYS[1])
else
return 0
end
优点:
- 原子性好,不会出现死锁。
- 简单且实用,推荐使用。
3️⃣ Redisson 框架实现分布式锁
实现思路:
- Redisson 是基于 Redis 的高性能分布式工具,提供了 RLock 接口。
- 内部使用
SET NX PX
并自动续期。 - 支持可重入锁、公平锁、读写锁等。
val lock = redisson.getLock("myLock")
lock.lock(10, TimeUnit.SECONDS) // 自动释放
try {
// 业务处理
} finally {
lock.unlock()
}
优点:
- 功能丰富,支持高级特性。
- 自动续期和超时,减少死锁风险。
缺点:
- 引入额外依赖,性能略低于直接使用 Redis 命令。
4️⃣ RedLock 算法(推荐分布式场景)
实现思路:
- Redis 官方推荐的分布式锁算法。
- 在 多个 Redis 实例 上尝试加锁,只有获得大多数节点锁才算成功。
- 使用
SET NX PX
实现。
优点:
- 高可用,单点故障不会导致整个锁失效。
- 适合跨机房、分布式高可用场景。
缺点:
- 实现复杂,需要多个 Redis 实例。
- 在网络抖动情况下可能出现锁漂移。
5️⃣ WATCH + MULTI/EXEC(事务实现锁)
实现思路:
- 使用 Redis 的 乐观锁机制。
WATCH
监控锁 key,确保在事务执行期间 key 没有变化。- 使用
MULTI
/EXEC
提交原子操作。
WATCH lock_key
if redis.get(lock_key) == nil then
MULTI
SET lock_key request_id
EXPIRE lock_key 10
EXEC
end
优点:
- 利用 Redis 事务保证操作原子性。
- 避免多个客户端竞争锁时覆盖问题。
缺点:
- 复杂,效率比 SET NX PX 低。
- 乐观锁可能导致重试次数过多。
6️⃣ 自旋锁(Spin Lock)
实现思路:
- 通过循环尝试获取锁,直到成功或超时。
- 适合短时间操作,避免阻塞线程。
while (true) {
val result = jedis.set("lock", requestId, "NX", "PX", 10000)
if (result == "OK") break
Thread.sleep(50) // 等待一段时间后重试
}
优点:
- 简单易实现。
- 可避免瞬时冲突导致锁失败。
缺点:
- 频繁循环消耗 CPU,不适合长时间持锁。
- 需要合理设置等待时间和超时时间。
7️⃣ 带续期的自动锁(Watchdog / TTL 自动续期)
实现思路:
- 锁过期时间过短,可能在业务处理未完成时被释放。
- 可以通过 Watchdog 或后台协程自动延长 TTL,确保业务完成。
- Redisson 内部默认实现了 Watchdog。
示例:
val lock = redisson.getLock("myLock")
lock.lock() // 无需指定时间,Redisson Watchdog 会自动续期
优点:
- 避免锁过期导致业务未完成就被释放。
- 简化业务逻辑,无需手动续期。
缺点:
- 增加 Redis 消息传输,略微增加开销。
✅ 总结对比表
方案 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
SETNX + EXPIRE | 简单 | 不是原子操作,可能死锁 | 单机简单场景 |
SET NX PX | 原子,简单可靠 | 无跨实例容错 | 单机 Redis 分布式锁 |
Redisson | 高级功能(续期、可重入) | 引入依赖 | 企业级应用 |
RedLock | 高可用,防单点故障 | 实现复杂 | 多节点高可用分布式系统 |
WATCH + MULTI/EXEC | 原子操作,事务保证 | 实现复杂,效率低 | 事务锁场景 |
自旋锁 | 简单,快速 | CPU 消耗大 | 短时间锁,瞬时冲突 |
自动续期锁 | 防止业务未完成锁过期 | 需要后台续期 | 长时间任务,企业应用 |
发表回复