【Redis】告别锁失效:RedLock 与 ZooKeeper 分布式锁原理与实战对比

红锁(RedLock)

先回顾问题:普通 Redis 锁为啥会失效?

你想租一个单间(分布式锁),房东只有 1 把钥匙(单 Redis 主节点),你拿到钥匙锁了门(加锁成功),但房东还没来得及把「你锁门」的消息告诉隔壁中介(从节点),房东就突然失联了(主节点宕机)。隔壁中介接手后(从节点升级为主),不知道你锁了门,又把钥匙给了另一个租客(其他客户端加锁),结果你们俩都能进这个房间 ------ 这就是普通 Redis 锁的主从一致性问题。

红锁的核心逻辑:「多把钥匙,过半才算数」

红锁的思路很简单:不依赖单把钥匙,而是找 3 个及以上独立的房东(独立 Redis 节点,无主从关系),必须拿到「超过一半房东」的钥匙,才算真正锁上门

具体步骤(用 3 个房东举例,核心是「过半」):
  1. 你找房东 A、B、C 分别要钥匙(向 3 个独立 Redis 节点发起加锁请求);
  2. 拿到至少 2 把钥匙(过半)才算成功
    • 如果你拿到 A 和 B 的钥匙,哪怕 C 拒绝 / 失联,也算「锁门成功」;
    • 如果你只拿到 A 的钥匙(不足半),就不算锁成功,得把拿到的钥匙都还回去(解锁所有节点);
  1. 其他租客想锁门,必须也拿到至少 2 把钥匙
    • 因为你已经拿了 A 和 B 的钥匙,其他租客最多只能拿到 C 的,不足半,所以根本锁不了门;
  1. 就算 1 个房东失联(节点宕机)也不怕
    • 比如房东 A 失联了,你手里还有 B 的钥匙,其他租客最多拿到 C 的,还是不足半,锁依然有效;
  1. 你走的时候,把所有房东的钥匙都还回去(解锁所有节点),其他租客才能重新抢钥匙。

核心关键点(通俗总结):

  1. 节点必须独立:3 个房东互不认识、不互通消息(无主从同步),避免「一个失联,全乱套」;
  2. 过半是核心:3 个节点要拿≥2 把,5 个节点要拿≥3 把,只要超过一半,锁就安全;
  3. 超时要控制:找每个房东要钥匙的总时间,不能超过你计划锁门的时间的一半(比如你想锁 30 秒,找 3 个房东的总耗时不能超过 15 秒),避免钥匙还没拿完,之前拿到的已经过期了。

红锁为啥能解决主从问题?

普通锁是「一根绳上的蚂蚱」,主节点宕机就全完;红锁是「多根绳」,只要超过一半的绳没断(节点正常),锁就不会失效。哪怕 1 个节点宕机,剩下的节点还能保证「只有一个人能拿到过半钥匙」,不会出现多人同时锁门的情况。

红锁的缺点(还是用租房举例):

  1. 麻烦又慢:找 3 个房东要钥匙,比找 1 个费时间(性能下降);
  2. 成本高:要养 3 个独立的房东(部署 3 组 Redis 节点),花钱又费精力(运维成本高);
  3. 极端情况仍有风险:如果 3 个房东的手表时间不一致(节点时钟偏移),可能出现「你以为还拿着钥匙,其实已经过期」的情况。

最终总结:

红锁的核心就是「多节点投票,过半生效」------ 用多个独立 Redis 节点代替单节点,通过「超过半数节点加锁成功」的规则,抵消单个节点宕机带来的锁失效问题,本质是用「性能和运维成本」换「更高的一致性」。用和红锁同款的「租房锁门」场景,把ZooKeeper分布式锁的核心逻辑讲得明明白白,保证比红锁还好懂:

Zookeeper

先定调:ZK锁的核心思路和红锁完全不同

红锁是「多把钥匙凑过半」,靠数量兜底;ZK锁是「排号进门+实时监控」,靠强一致性从根上避免问题------ZK天生就是为「分布式一致性」设计的,不像Redis是为「高性能」设计的。

用租房场景讲ZK锁的核心逻辑

还是租房锁门的例子,ZK就像一个「官方租房管理处」,规则特别严,所有租客都必须按它的规矩来:

第一步:管理处的「排号规则」(临时有序节点)

ZK里没有「钥匙」的概念,而是靠「排号单」管理:

  1. 所有想租房的租客(客户端),都要去管理处领一张「排号单」(在ZK的 /lock 节点下创建「临时有序子节点」,比如 lock-00000001lock-00000002);
  2. 「临时」的意思:如果租客失联(客户端宕机/网络断了),排号单会自动作废(节点删除),不会占着位置;
  3. 「有序」的意思:管理处按租客来的顺序排号,先到的号小,后到的号大。
第二步:「号最小的才能锁门」(公平锁核心)
  1. 你领了排号单(比如 lock-00000001),然后去问管理处:「我是不是当前号最小的?」;
  2. 管理处说「是」,你就能锁门(加锁成功),其他人都得等着;
  3. 如果你的号不是最小的(比如是 lock-00000002),你就只能盯着前一个号的租客(lock-00000001),等他走了再说(监听前一个节点的删除事件)。
第三步:「走了必须销号」(解锁+实时通知)
  1. 你租完房走的时候,要去管理处销号(删除自己的节点),管理处会立刻通知下一个排号的租客(触发监听事件);
  2. 下一个租客收到通知后,再去问管理处「我是不是最小的?」,确认后就能锁门------全程只有一个租客能锁门。
第四步:「管理处宕机也不怕」(ZK的CP特性)

ZK本身也有主从,但和Redis不一样:

  1. Redis主从是「异步同步」(主节点锁门了,从节点可能还不知道);
  2. ZK主从是「同步同步」(主节点给你排号后,必须等所有从节点都记下来,才告诉你「排号成功」);
  3. 就算ZK主节点宕机,从节点升级为主,你的排号单还在,管理处的规则没变,不会出现「重复排号」的情况。

ZK锁为啥能解决Redis的一致性问题?

Redis锁的问题是「消息没同步就失联」,而ZK锁:

  1. 「临时节点」:客户端宕机自动销号,不会占着锁不放;
  2. 「同步一致性」:主节点的排号记录一定会同步给从节点,不会丢数据;
  3. 「排号+监听」:全程只有一个人能拿到锁,从根上保证互斥性。

ZK锁的缺点(还是租房举例)

  1. 慢一点:管理处要挨个排号、同步记录,比Redis「一把钥匙」的方式慢(性能不如Redis);
  2. 规则严:如果管理处(ZK集群)挂了一半以上节点,就彻底不能办业务了(CP模型,牺牲可用性换一致性);
  3. 略复杂:租客要排号、监听、确认,流程比直接拿钥匙繁琐(开发/运维成本比Redis高)。

核心总结(一句话)

ZK分布式锁的核心是「排号进门,实时监听,同步记账」------靠有序排队保证互斥,靠临时节点防死锁,靠同步一致性防数据丢失,天生解决Redis主从的锁失效问题,但代价是性能和可用性稍差。

相关推荐
博界IT精灵2 小时前
循环链表(包括循环单链表、循环双链表)
数据结构·链表
JTCC2 小时前
Java 设计模式西游篇 - 第八回:适配器模式通万国 女儿国语言无障碍
python·设计模式·适配器模式
敲个大西瓜2 小时前
flask ApI快速上手
python
SuperEugene2 小时前
Promise 从入门到实战:同步异步、回调地狱、then/catch/finally 全解
前端·javascript·面试
浩瀚之水_csdn2 小时前
【框架】flask路由深度解析
后端·python·flask
lars_lhuan2 小时前
Go 方法
开发语言·后端·golang
前端 贾公子2 小时前
uniapp 小程序获取后端的二进制 保存到手机相册
java·前端·javascript
希望永不加班2 小时前
Spring Boot 统一异常处理:从混乱到优雅的实用方案
java·spring boot·后端·spring·状态模式
8Qi82 小时前
环形链表刷题笔记(LeetCode热题100--141、142)
c语言·数据结构·c++·算法·leetcode·链表