直接回答

基础实现:用 SET key value NX EX 原子地完成"不存在才设置 + 过期时间",value 存唯一标识(如 UUID)。释放锁时用 Lua 脚本原子执行"比对 value 再删除",防止误删别人的锁。生产上还要解决锁续期(看门狗)和主从切换丢锁问题,推荐直接用 Redisson,强一致要求高的场景考虑 RedLock 或改用基于共识协议的组件。

展开解析

需要绕过的坑:

  1. 加锁非原子:早期 SETNX + EXPIRE 两条命令,客户端在中间崩溃会导致锁永不释放——必须用带 NX/EX 参数的 SET 一条命令完成。
  2. 误删:线程 A 业务没执行完锁就过期,线程 B 拿到锁后,A 执行完把 B 的锁删了——value 存唯一标识,删前校验,且"GET + DEL"必须 Lua 原子执行。
  3. 锁续期:业务执行时间不可控,过期时间设短了锁提前释放,设长了崩溃后等待久——Redisson 的看门狗在持有期间自动续期(默认每 10 秒续到 30 秒)。
  4. 主从切换丢锁:锁写入主节点后还没同步到从节点,主宕机从升级,锁丢失——RedLock 向多数独立节点加锁缓解,但有争议(Martin Kleppmann 与 antirez 的著名论战);对正确性要求极高的场景用 ZooKeeper/etcd 更稳。
SET lock:order:1 7f3a-uuid NX EX 30   # 加锁
# Lua: if get(key)==value then del(key) end  # 解锁

追问方向:可重入锁实现(Hash 结构存线程标识+计数)、锁粒度与性能。