红锁(RedLock)
先回顾问题:普通 Redis 锁为啥会失效?
你想租一个单间(分布式锁),房东只有 1 把钥匙(单 Redis 主节点),你拿到钥匙锁了门(加锁成功),但房东还没来得及把「你锁门」的消息告诉隔壁中介(从节点),房东就突然失联了(主节点宕机)。隔壁中介接手后(从节点升级为主),不知道你锁了门,又把钥匙给了另一个租客(其他客户端加锁),结果你们俩都能进这个房间 ------ 这就是普通 Redis 锁的主从一致性问题。
红锁的核心逻辑:「多把钥匙,过半才算数」
红锁的思路很简单:不依赖单把钥匙,而是找 3 个及以上独立的房东(独立 Redis 节点,无主从关系),必须拿到「超过一半房东」的钥匙,才算真正锁上门。
具体步骤(用 3 个房东举例,核心是「过半」):
- 你找房东 A、B、C 分别要钥匙(向 3 个独立 Redis 节点发起加锁请求);
- 拿到至少 2 把钥匙(过半)才算成功:
-
- 如果你拿到 A 和 B 的钥匙,哪怕 C 拒绝 / 失联,也算「锁门成功」;
- 如果你只拿到 A 的钥匙(不足半),就不算锁成功,得把拿到的钥匙都还回去(解锁所有节点);
- 其他租客想锁门,必须也拿到至少 2 把钥匙:
-
- 因为你已经拿了 A 和 B 的钥匙,其他租客最多只能拿到 C 的,不足半,所以根本锁不了门;
- 就算 1 个房东失联(节点宕机)也不怕:
-
- 比如房东 A 失联了,你手里还有 B 的钥匙,其他租客最多拿到 C 的,还是不足半,锁依然有效;
- 你走的时候,把所有房东的钥匙都还回去(解锁所有节点),其他租客才能重新抢钥匙。
核心关键点(通俗总结):
- 节点必须独立:3 个房东互不认识、不互通消息(无主从同步),避免「一个失联,全乱套」;
- 过半是核心:3 个节点要拿≥2 把,5 个节点要拿≥3 把,只要超过一半,锁就安全;
- 超时要控制:找每个房东要钥匙的总时间,不能超过你计划锁门的时间的一半(比如你想锁 30 秒,找 3 个房东的总耗时不能超过 15 秒),避免钥匙还没拿完,之前拿到的已经过期了。
红锁为啥能解决主从问题?
普通锁是「一根绳上的蚂蚱」,主节点宕机就全完;红锁是「多根绳」,只要超过一半的绳没断(节点正常),锁就不会失效。哪怕 1 个节点宕机,剩下的节点还能保证「只有一个人能拿到过半钥匙」,不会出现多人同时锁门的情况。
红锁的缺点(还是用租房举例):
- 麻烦又慢:找 3 个房东要钥匙,比找 1 个费时间(性能下降);
- 成本高:要养 3 个独立的房东(部署 3 组 Redis 节点),花钱又费精力(运维成本高);
- 极端情况仍有风险:如果 3 个房东的手表时间不一致(节点时钟偏移),可能出现「你以为还拿着钥匙,其实已经过期」的情况。
最终总结:
红锁的核心就是「多节点投票,过半生效」------ 用多个独立 Redis 节点代替单节点,通过「超过半数节点加锁成功」的规则,抵消单个节点宕机带来的锁失效问题,本质是用「性能和运维成本」换「更高的一致性」。用和红锁同款的「租房锁门」场景,把ZooKeeper分布式锁的核心逻辑讲得明明白白,保证比红锁还好懂:
Zookeeper
先定调:ZK锁的核心思路和红锁完全不同
红锁是「多把钥匙凑过半」,靠数量兜底;ZK锁是「排号进门+实时监控」,靠强一致性从根上避免问题------ZK天生就是为「分布式一致性」设计的,不像Redis是为「高性能」设计的。
用租房场景讲ZK锁的核心逻辑
还是租房锁门的例子,ZK就像一个「官方租房管理处」,规则特别严,所有租客都必须按它的规矩来:
第一步:管理处的「排号规则」(临时有序节点)
ZK里没有「钥匙」的概念,而是靠「排号单」管理:
- 所有想租房的租客(客户端),都要去管理处领一张「排号单」(在ZK的
/lock节点下创建「临时有序子节点」,比如lock-00000001、lock-00000002); - 「临时」的意思:如果租客失联(客户端宕机/网络断了),排号单会自动作废(节点删除),不会占着位置;
- 「有序」的意思:管理处按租客来的顺序排号,先到的号小,后到的号大。
第二步:「号最小的才能锁门」(公平锁核心)
- 你领了排号单(比如
lock-00000001),然后去问管理处:「我是不是当前号最小的?」; - 管理处说「是」,你就能锁门(加锁成功),其他人都得等着;
- 如果你的号不是最小的(比如是
lock-00000002),你就只能盯着前一个号的租客(lock-00000001),等他走了再说(监听前一个节点的删除事件)。
第三步:「走了必须销号」(解锁+实时通知)
- 你租完房走的时候,要去管理处销号(删除自己的节点),管理处会立刻通知下一个排号的租客(触发监听事件);
- 下一个租客收到通知后,再去问管理处「我是不是最小的?」,确认后就能锁门------全程只有一个租客能锁门。
第四步:「管理处宕机也不怕」(ZK的CP特性)
ZK本身也有主从,但和Redis不一样:
- Redis主从是「异步同步」(主节点锁门了,从节点可能还不知道);
- ZK主从是「同步同步」(主节点给你排号后,必须等所有从节点都记下来,才告诉你「排号成功」);
- 就算ZK主节点宕机,从节点升级为主,你的排号单还在,管理处的规则没变,不会出现「重复排号」的情况。
ZK锁为啥能解决Redis的一致性问题?
Redis锁的问题是「消息没同步就失联」,而ZK锁:
- 「临时节点」:客户端宕机自动销号,不会占着锁不放;
- 「同步一致性」:主节点的排号记录一定会同步给从节点,不会丢数据;
- 「排号+监听」:全程只有一个人能拿到锁,从根上保证互斥性。
ZK锁的缺点(还是租房举例)
- 慢一点:管理处要挨个排号、同步记录,比Redis「一把钥匙」的方式慢(性能不如Redis);
- 规则严:如果管理处(ZK集群)挂了一半以上节点,就彻底不能办业务了(CP模型,牺牲可用性换一致性);
- 略复杂:租客要排号、监听、确认,流程比直接拿钥匙繁琐(开发/运维成本比Redis高)。
核心总结(一句话)
ZK分布式锁的核心是「排号进门,实时监听,同步记账」------靠有序排队保证互斥,靠临时节点防死锁,靠同步一致性防数据丢失,天生解决Redis主从的锁失效问题,但代价是性能和可用性稍差。