分布式锁实现:Redis setnx 与 ZooKeeper 对比

一、为什么需要分布式锁

单机用 mutex 就够了;多实例部署时,多个进程同时”抢一个资源”(如定时任务只跑一次、库存扣减),就需要跨进程的锁。分布式锁就是让任意时刻只有一个节点能拿到执行权。

二、Redis 实现(setnx + 过期)

-- 原子加锁:不存在才设,并带过期防死锁
SET lock:order:1001 "nodeA" NX PX 30000

-- 释放锁要用 Lua,保证"只删自己的锁"(防误删别人的)
if redis.call("get", KEYS[1]) == ARGV[1] then
    return redis.call("del", KEYS[1])
end

要点:加锁必须带过期时间防崩溃死锁;释放必须校验持有者,否则可能删掉别人刚拿到的锁。

三、自动续期(看门狗)

业务没跑完锁就过期了怎么办?拿锁的客户端起一个守护任务,在过期前持续续期;释放时停掉续期并删锁。Redisson 等库已封装这套逻辑。

四、Redlock 与 ZooKeeper

方案 特点
Redis 单节点 简单,但主从切换瞬间可能丢锁,强一致场景慎用
Redlock 多节点多数派加锁,提高可用性
ZooKeeper 临时顺序节点,崩溃自动释放,强一致但运维重

五、落地建议

  • 能不用分布式锁就不用——优先用数据库唯一约束、乐观锁;
  • 锁粒度尽量小,别锁一整张表;
  • 务必设超时,杜绝死锁;
  • 业务层加幂等兜底,锁失效也不致资损。

分布式锁是”最后一道并发闸门”,配合幂等和超时,才能在高并发下既正确又安全。