一、为什么需要分布式锁
单机用 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 | 临时顺序节点,崩溃自动释放,强一致但运维重 |
五、落地建议
- 能不用分布式锁就不用——优先用数据库唯一约束、乐观锁;
- 锁粒度尽量小,别锁一整张表;
- 务必设超时,杜绝死锁;
- 业务层加幂等兜底,锁失效也不致资损。
分布式锁是”最后一道并发闸门”,配合幂等和超时,才能在高并发下既正确又安全。