好的,我帮你整理一篇 Redis 实现分布式锁的7种方案及正确使用方法,涵盖实现思路、优缺点和最佳实践。
Redis 实现分布式锁的 7 种方案及正确使用姿势
1️⃣ 分布式锁的场景
在分布式系统中,多个服务实例可能会 同时访问共享资源(数据库、文件、库存等)。
为了保证互斥访问,需要使用分布式锁。
2️⃣ Redis 分布式锁基本原理
- 利用 SETNX(SET if Not Exists) 或 SET key value NX PX expire 命令创建锁
- 锁的 value 一般存储唯一标识(UUID),用于释放锁时验证自己是否持有锁
- 设置 过期时间 防止死锁
3️⃣ Redis 实现分布式锁的 7 种方案
方案1:SETNX + EXPIRE
SETNX lock_key UUID // 获取锁
EXPIRE lock_key 10 // 设置过期时间
✅ 优点:简单
❌ 缺点:SETNX 和 EXPIRE 非原子操作,可能导致死锁
方案2:SETNX + GETSET
SETNX lock_key UUID
GETSET lock_key UUID // 用于续期或抢锁
✅ 优点:避免死锁
❌ 缺点:仍然有竞争条件,非完全安全
方案3:SET key value NX PX expire(推荐)
SET lock_key UUID NX PX 10000
- NX:仅在 key 不存在时设置
- PX:设置过期时间(毫秒)
✅ 优点:原子操作,简单可靠
❌ 缺点:锁过期后自动释放,可能被误解锁
方案4:Lua 脚本释放锁
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
- 先判断 UUID 是否匹配,再删除锁
✅ 优点:避免误删他人的锁
❌ 缺点:需要写 Lua 脚本
方案5:Redisson(Java客户端)实现分布式锁
RLock lock = redissonClient.getLock("lockKey");
lock.lock(10, TimeUnit.SECONDS); // 自动续期
try {
// 执行业务逻辑
} finally {
lock.unlock();
}
✅ 优点:简单易用,自动续期和安全
❌ 缺点:依赖第三方库
方案6:Redlock(Redis 官方推荐算法)
- 原理:在 多个 Redis 实例 上同时加锁,需获得多数实例的锁才算成功
- 提高了可靠性,防止单点故障
✅ 优点:安全性更高,分布式环境下推荐
❌ 缺点:实现复杂,延迟敏感
方案7:利用 List + BLPOP 模拟锁(阻塞队列方式)
- 将锁请求加入队列,使用 BLPOP 阻塞等待获取锁
✅ 优点:公平锁,按顺序获取
❌ 缺点:实现复杂,性能受阻塞影响
4️⃣ Redis 分布式锁最佳实践
- 锁必须设置过期时间,防止死锁
- 释放锁时检查 UUID,避免误删别人锁
- 避免业务执行时间超过锁过期时间,可考虑自动续期
- 使用可靠客户端(如 Redisson)或 Redlock 算法
- 不适合强一致性场景,只保证互斥性和最终一致性
5️⃣ 推荐姿势
- 简单场景:
SET key value NX PX expire + Lua 释放
- 高可靠场景:Redisson 或 Redlock
- Java 实战示例:
RLock lock = redissonClient.getLock("orderLock");
try {
if(lock.tryLock(5, 10, TimeUnit.SECONDS)){
// 执行关键业务
}
} finally {
lock.unlock();
}
✅ 可保证安全、自动续期、异常释放
💡 总结:
- Redis 分布式锁方案很多,核心都是 SETNX + 过期时间 + UUID验证
- Lua 脚本和 Redisson 提供了安全和易用的方式
- 分布式环境下优先使用 Redlock 或 Redisson
发表回复