非常好的问题 👍
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 标识客户端

加锁流程:

  1. 客户端生成唯一 UUID
  2. 顺序尝试获取锁(带超时)
  3. 超过半数成功 → 加锁成功
  4. 否则 → 释放已获取的锁,重试

✅ 优点:

  • 高可靠,不依赖单节点
  • 容忍部分节点宕机

⚠️ 缺点:

  • 实现复杂
  • 延迟高、时钟漂移风险
  • Redis 官方后来认为该算法仅理论安全,不推荐生产使用

🧩 六、Pub/Sub 通知锁

使用 Redis 的发布订阅机制,当锁释放时通知其他等待者。

流程:

  1. 客户端尝试加锁失败 → 订阅 unlock_channel
  2. 释放锁时 → 发布通知
  3. 等待者收到通知 → 再尝试加锁

✅ 优点:

  • 避免轮询(节省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 锁。