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

优点:

  • 实现简单,原子性较高。

缺点:

  • SETNXEXPIRE 不是原子操作,可能在服务崩溃时造成死锁。
  • 锁释放存在误删风险(必须用唯一标识 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 消耗大短时间锁,瞬时冲突
自动续期锁防止业务未完成锁过期需要后台续期长时间任务,企业应用