好的,我帮你整理一篇 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 分布式锁最佳实践

  1. 锁必须设置过期时间,防止死锁
  2. 释放锁时检查 UUID,避免误删别人锁
  3. 避免业务执行时间超过锁过期时间,可考虑自动续期
  4. 使用可靠客户端(如 Redisson)或 Redlock 算法
  5. 不适合强一致性场景,只保证互斥性和最终一致性

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