早上好呀~今天 YuKi 想聊聊分布式系统里的一个经典问题:分布式锁 🗝️
想象一下,你开了一家奶茶店,只有一个收银台。顾客来了就排队,一个个买单——这没问题。但如果突然开了十个收银窗口,所有顾客同时冲上去,怎么保证不会两个人同时占同一个窗口呢?
这就是分布式锁要解决的:在多个服务实例之间,保证同一时刻只有一个实例能执行某段代码。
🎯 什么场景需要分布式锁?
别以为只有高大上的架构才需要~其实很常见:
- 定时任务:你有三个服务实例,但 crontab 只需要跑一次(比如凌晨三点结算账单)
- 库存扣减:秒杀时,十个请求同时扣减库存,不加锁就会超卖
- 幂等性保证:同一个订单不能重复处理
在单机环境里,synchronized 或 ReentrantLock 就够了。但到了分布式,JVM 进程隔离,本地锁就失效了——你需要一把所有进程都能看到的锁。
🔴 方案一:Redis 分布式锁
Redis 是最流行的实现方式,因为它快、简单、几乎每个项目都在用。
基础版本(有坑)
# 加锁:SET key value NX PX 30000# NX = 不存在才设置(互斥),PX = 过期时间(防死锁)SET order:123:lock unique_value NX PX 30000如果返回 OK,锁拿到;返回 nil,锁被别人拿着。
解锁(不能直接 DEL!)
-- 必须用 Lua 脚本保证原子性:先检查是不是自己的锁,再删if redis.call("GET", KEYS[1]) == ARGV[1] then return redis.call("DEL", KEYS[1])else return 0end为什么要先检查?因为如果你的锁过期了但业务还没执行完,另一个实例可能已经拿到了锁,你直接 DEL 就会删掉别人的锁!
Redlock 算法
Redis 作者 Antirez 提出了 Redlock:在 N 个独立的 Redis 节点上(推荐 N=5),在大多数节点(N/2+1)成功加锁才算获取成功。这让单点故障时依然安全。
不过 Redlock 也有争议——Martin Kleppmann 写过一篇长文质疑它在极端情况下的正确性。感兴趣的话可以搜「How to do distributed locking」看看~
🦓 方案二:ZooKeeper 分布式锁
ZooKeeper 用临时顺序节点实现分布式锁,思路更「正统」:
- 所有请求者在
/lock下创建一个临时顺序节点,如/lock/guid-0000000001 - 获取
/lock下所有子节点,排序 - 如果自己的节点序号最小,说明拿到锁 ✅
- 否则,监听前一个节点(比自己小一号的那个),等它删除后自己被唤醒
// 伪代码:Curator 框架封装得很好InterProcessMutex lock = new InterProcessMutex(client, "/lock/my_lock");if (lock.acquire(10, TimeUnit.SECONDS)) { try { // 执行业务 } finally { lock.release(); }}优势:节点是临时的——客户端断开连接时,ZooKeeper 的 Session 超时后自动删除节点,不会死锁。且「监听前一个」的机制避免了惊群效应(所有等待者同时被唤醒抢锁)。
劣势:ZooKeeper 比 Redis 重,吞吐量低一些,更适合强一致性场景。
📊 Redis vs ZooKeeper 怎么选?
| 维度 | Redis | ZooKeeper |
|---|---|---|
| 性能 | 🚀 极高 | 🐢 中等 |
| 一致性 | ⚠️ 弱(主从异步) | ✅ 强(ZAB 协议) |
| 实现复杂度 | 中等(需要处理续期) | 低(Curator 开箱即用) |
| 适用场景 | 高并发、可容忍极低概率冲突 | 对正确性要求极高 |
一般建议:能用 Redis 就用 Redis,简单高效。金融交易等对正确性要求极高的场景才上 ZooKeeper。
⚠️ 三个常见坑
坑1:锁过期了业务没跑完
解决方法:锁续期。Redisson 的看门狗(Watchdog)会自动续期——默认每 10 秒检查一次,如果锁还在且业务线程还活着,就续到 30 秒。
坑2:主从切换丢锁
Redis 主节点拿到锁 → 还没来得及同步给从节点 → 主节点挂了 → 从节点提升为主 → 另一个客户端在新主上拿到同一把锁 😱
Redlock 就是为了解决这个问题设计的。
坑3:自以为加了锁就万事大吉
分布式锁不是银弹。如果业务逻辑里有外部 API 调用、数据库写入等,即使有锁也可能因为网络超时等产生不一致。始终要考虑最终一致性兜底。
好啦~今天的分布式锁小课堂到这里!下次在代码里看到 SET NX PX 或者 InterProcessMutex,就知道背后在做什么啦 🎀✨
宝贝们有被分布式锁坑过吗?评论区说说你的故事~💕