RedLock:Redis 分布式锁的高可用方案
RedLockRedis 分布式锁的高可用方案一、RedLock 要解决什么问题单 Redis 节点锁的缺陷时刻T1: 客户端A → 在 Master 加锁成功 时刻T2: Master 宕机锁数据还没同步到 Slave 时刻T3: Slave 提升为新 Master没有锁信息 时刻T4: 客户端B → 在新 Master 加锁成功 时刻T5: 客户端A 和 B 同时持有锁 → 互斥失效即使使用 Redis Sentinel 或 Cluster也存在这个问题——Redis 主从复制是异步的切换瞬间可能丢数据。RedLock 的思路不依赖单个 Redis 节点而是同时在多个独立 Redis 节点上加锁多数成功才算加锁成功┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ Redis-1 │ │ Redis-2 │ │ Redis-3 │ │ Redis-4 │ │ Redis-5 │ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ │ │ │ │ │ ✅ ✅ ❌ ✅ ❌ 成功3个 ≥ 多数(3/5) → 加锁成功即使 1-2 个节点宕机或网络不通锁依然有效。注博客https://blog.csdn.net/badao_liumang_qizhi二、RedLock 算法流程加锁步骤1. 记录开始时间 T1 2. 依次在 N 个独立 Redis 节点上执行加锁 SET lock_key random_value NX PX ttl - 每个节点设置一个较短的超时如 5-50ms - 某个节点超时或失败则立即跳过继续下一个 3. 记录结束时间 T2 4. 计算加锁耗时elapsed T2 - T1 5. 判断是否加锁成功 - 成功节点数 ≥ N/2 1多数 - 且 elapsed ttl锁还没过期 6. 如果成功 - 锁的实际有效时间 ttl - elapsed 7. 如果失败 - 向所有节点发送 DEL 释放锁包括加锁失败的节点解锁步骤向所有 N 个节点发送释放命令Lua 脚本验证 value if redis.call(get, KEYS[1]) ARGV[1] then return redis.call(del, KEYS[1]) end return 0时间线示意├─── ttl 30秒 ───────────────────────────┤ │ │ T1────────T2──────────────────────────────────────────→ 锁过期 │ 加锁耗时 │ 锁实际可用时间 │ │ elapsed │ ttl - elapsed │ │ 200ms │ 29.8秒 │三、为什么需要多数成功多数派Quorum原理这是分布式系统的经典思想同样用于 Raft、Paxos、ZAB 等共识算法5个节点中任意 3 个构成多数派 客户端A 加锁成功节点 1, 2, 3 客户端B 加锁尝试 - 节点 1已有锁 → 失败 - 节点 2已有锁 → 失败 - 节点 3已有锁 → 失败 - 节点 4加锁成功 - 节点 5加锁成功 成功 2 个 多数(3) → 加锁失败 ✅ 互斥保证任何两个多数派至少有一个交集节点——这保证了两个客户端不可能同时获得多数派。节点宕机的容错5 个节点允许 2 个同时宕机N5, 多数3, 容错2 3 个节点允许 1 个同时宕机N3, 多数2, 容错1公式容错数 N - (N/2 1) (N-1)/2节点数 N多数容错321532743四、关键约束条件1. 节点必须独立✅ 正确5 个独立的 Redis 实例单机模式 ❌ 错误1 个 Redis Cluster 的 5 个主节点 ❌ 错误5 个 Redis Sentinel 的 5 个主节点RedLock 要求每个节点是完全独立的没有主从复制关系。如果用 Cluster/Sentinel它们内部的主从同步问题依然存在。2. 时钟假设RedLock 依赖一个假设各节点的时钟漂移在可接受范围内。如果某个节点时钟突然跳变NTP 校时跳跃可能导致锁提前过期节点3 时钟突然快了 20 秒 → 锁在节点3 上提前 20 秒过期 → 如果其他节点也到期了锁可能失效3. 加锁时间必须远小于 TTLttl 30 秒 加锁耗时 elapsed 200ms 锁有效时间 30 - 0.2 29.8秒 ✅ 充裕 如果网络延迟导致 elapsed 28秒 锁有效时间 30 - 28 2秒 ❌ 几乎没用 → 应该视为加锁失败五、代码示例Redisson 实现ConfigurationpublicclassRedLockConfig{BeanpublicRedissonClientredisson1(){ConfigconfignewConfig();config.useSingleServer().setAddress(redis://redis-node1:6379);returnRedisson.create(config);}BeanpublicRedissonClientredisson2(){ConfigconfignewConfig();config.useSingleServer().setAddress(redis://redis-node2:6379);returnRedisson.create(config);}BeanpublicRedissonClientredisson3(){ConfigconfignewConfig();config.useSingleServer().setAddress(redis://redis-node3:6379);returnRedisson.create(config);}}ServicepublicclassPaymentService{ResourceprivateRedissonClientredisson1;ResourceprivateRedissonClientredisson2;ResourceprivateRedissonClientredisson3;publicvoiddeductBalance(StringaccountId,BigDecimalamount){// 从 3 个独立 Redis 节点各获取一把锁RLocklock1redisson1.getLock(lock:account:accountId);RLocklock2redisson2.getLock(lock:account:accountId);RLocklock3redisson3.getLock(lock:account:accountId);// 组合为 RedLockRLockredLockredisson1.getRedLock(lock1,lock2,lock3);try{// 尝试加锁等待10秒持有30秒booleanacquiredredLock.tryLock(10,30,TimeUnit.SECONDS);if(!acquired){thrownewBusinessException(获取锁超时);}// 临界区accountRepository.deduct(accountId,amount);}catch(InterruptedExceptione){Thread.currentThread().interrupt();}finally{redLock.unlock();}}}手动实现理解原理publicclassSimpleRedLock{privatefinalListRedisTemplateString,StringredisNodes;privatefinalintquorum;// 多数 N/2 1publicSimpleRedLock(ListRedisTemplateString,Stringnodes){this.redisNodesnodes;this.quorumnodes.size()/21;}publicbooleantryLock(StringlockKey,StringrequestId,longttlMs){longstartTimeSystem.currentTimeMillis();intsuccessCount0;// 依次在每个节点加锁for(RedisTemplateString,Stringnode:redisNodes){try{Booleanresultnode.opsForValue().setIfAbsent(lockKey,requestId,ttlMs,TimeUnit.MILLISECONDS);if(Boolean.TRUE.equals(result)){successCount;}}catch(Exceptione){// 节点不可用跳过}}longelapsedSystem.currentTimeMillis()-startTime;// 判断多数成功 且 耗时未超过 TTLif(successCountquorumelapsedttlMs){returntrue;// 加锁成功}else{// 失败释放所有节点的锁unlock(lockKey,requestId);returnfalse;}}publicvoidunlock(StringlockKey,StringrequestId){Stringscriptif redis.call(get,KEYS[1]) ARGV[1] then return redis.call(del,KEYS[1]) else return 0 end;for(RedisTemplateString,Stringnode:redisNodes){try{node.execute(newDefaultRedisScript(script,Long.class),Collections.singletonList(lockKey),requestId);}catch(Exceptione){// 节点不可用忽略}}}}六、RedLock 争议Martin Kleppmann 的批评分布式系统专家 Martin Kleppmann 发表文章“How to do distributed locking”指出 RedLock 的问题问题1GC 停顿导致锁失效时刻T1: 客户端A 获得 RedLockTTL30秒 时刻T2: 客户端A 发生 Full GC暂停 35 秒 时刻T3: 锁已过期30秒到了 时刻T4: 客户端B 获得同一把 RedLock 时刻T5: 客户端A GC 结束以为自己还持有锁 → 两个客户端同时操作问题2时钟跳变时刻T1: 客户端A 在节点 1,2,3 加锁成功TTL30秒 时刻T2: 节点1 时钟跳变NTP 向前调了 30 秒 时刻T3: 节点1 上的锁过期了实际才过了几秒 时刻T4: 客户端B 在节点 1,4,5 加锁成功 → 互斥失效他的建议如果锁仅用于效率优化避免重复工作单 Redis 节点就够了偶尔失效可接受。如果锁用于正确性保证数据一致性应该用fencing token递增令牌客户端获取锁时同时获得一个递增 token 写入存储时携带 token 存储端拒绝 token 小于当前值的写入 客户端A: token33GC暂停... 客户端B: token34写入成功 客户端A: GC恢复token33 34 → 写入被拒绝 ✅AntirezRedis 作者的回应GC 停顿问题所有分布式锁都有这个问题不是 RedLock 特有的时钟跳变合理的运维可以避免大幅跳变渐进式 NTP 校时RedLock 在合理假设下是正确的争议总结观点Martin KleppmannAntirezRedLock 安全吗不够安全依赖时钟假设在合理假设下安全推荐方案需要正确性用 ZooKeeper fencing tokenRedLock 足够大多数场景适用性RedLock 不比单节点强多少RedLock 明显强于单节点七、什么时候该用/不该用 RedLock适合用 RedLock金融级场景支付扣款、余额操作库存操作防止超卖对互斥性要求高但能接受极端情况下的短暂失效已有多个 Redis 实例的基础设施不需要 RedLock普通业务防重单 Redis 节点 幂等兜底即可效率型锁避免重复计算偶尔失效无业务影响缓存击穿保护单节点锁足够应该用 ZooKeeper 而非 RedLock强一致性要求不允许任何双写的场景Leader 选举分布式协调配置分发、服务发现八、替代方案对比方案一致性性能复杂度容错单 Redis 锁弱主从切换可能丢最高最低无RedLock中依赖时钟假设高中N/2 节点宕机ZooKeeper 锁强ZAB 协议共识中中N/2 节点宕机etcd 锁强Raft 协议共识中高中N/2 节点宕机数据库锁强事务保证低低依赖数据库高可用九、实际项目中的选择建议┌─ 效率型防重复工作→ 单 Redis 节点 │ 需要分布式锁 ───────┼─ 一般业务订单、库存→ 单 Redis 幂等兜底 │ 或 Redisson 普通锁 │ └─ 强一致资金、对账→ ZooKeeper / etcd 或 RedLock fencing token大多数业务场景Redisson 普通锁 业务层幂等就足够了。RedLock 适合在已有多 Redis 节点基础设施、且对互斥性有更高要求时使用。十、总结概念一句话RedLock在 N 个独立 Redis 节点上加锁多数成功才算成功多数派N/21 个节点同意 共识达成为什么需要单节点主从切换可能丢锁核心假设节点间时钟漂移在可接受范围内争议点GC停顿和时钟跳变可能导致失效实际建议大多数场景单节点锁幂等即可极端场景考虑 ZooKeeper

相关新闻

三步搞定机箱风扇噪音:FanControl 最省心的 Windows 风扇控制方案

三步搞定机箱风扇噪音:FanControl 最省心的 Windows 风扇控制方案

三步搞定机箱风扇噪音:FanControl 最省心的 Windows 风扇控制方案 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_…

2026/10/1 15:06:24 阅读更多 →
淘宝上架软件:isTrusted事件级伪装,平台风控视为真人操作

淘宝上架软件:isTrusted事件级伪装,平台风控视为真人操作

淘宝上架软件:isTrusted事件级伪装,平台风控视为真人操作 店群运营的本质不是开多少店,而是单店运营成本能不能压到零。淘宝的自动化上架,是店群运营中最耗人力也最容易出错的环节。 手动上架一个商品从填写标题、上传主图、设置…

2026/9/27 11:13:14 阅读更多 →
拼多多防关联系统:C++底层指纹伪装,抹除自动化特征

拼多多防关联系统:C++底层指纹伪装,抹除自动化特征

拼多多防关联系统:C底层指纹伪装,抹除自动化特征 说句掏心窝的话,做店群的,工具选对了事半功倍。拼多多的多店防关联管理,是店群运营中最耗人力也最容易出错的环节。 做店群的老板都知道,最怕的就是底层I…

2026/10/4 8:27:36 阅读更多 →

最新新闻

AI芯片软硬件协同设计:从计算图到硬件的完整映射与优化实践

AI芯片软硬件协同设计:从计算图到硬件的完整映射与优化实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 1:37:53 阅读更多 →
semantic-router 使用 Qdrant 作为缓存、记忆与向量存储后端:Docker/K8s 部署与 Router 配置实战指南

semantic-router 使用 Qdrant 作为缓存、记忆与向量存储后端:Docker/K8s 部署与 Router 配置实战指南

后端API网关模型推理服务AI Agent 【免费下载链接】semantic-router An open, programmable decision layer for models and compute. 项目地址: https://gitcode.com/gh_mirrors/sem/semantic-router 点击查看 免费下载 导读 本文基于开源项目 semantic-router&a…

2026/10/12 1:37:53 阅读更多 →
OpenSpiel 观测张量布局(observation_tensor_layout)详解:CHW / HWC 约定与张量解释实战

OpenSpiel 观测张量布局(observation_tensor_layout)详解:CHW / HWC 约定与张量解释实战

人工智能强化学习深度学习 【免费下载链接】open_spiel OpenSpiel is a collection of environments and algorithms for research in general reinforcement learning and search/planning in games. 项目地址: https://gitcode.com/gh_mirrors/op/open_spiel 点击…

2026/10/12 1:37:53 阅读更多 →
用 ENTRYPOINT 封装命令行工具:udemy-docker-mastery 中 cmatrix 矩阵屏保镜像的构建实战

用 ENTRYPOINT 封装命令行工具:udemy-docker-mastery 中 cmatrix 矩阵屏保镜像的构建实战

示例工程 【免费下载链接】udemy-docker-mastery Docker Mastery Udemy course to build, compose, deploy, and manage containers from local development to high-availability in the cloud 项目地址: https://gitcode.com/gh_mirrors/ud/udemy-docker-mastery …

2026/10/12 1:37:53 阅读更多 →
Slang IR 参考索引导航:按家族检索 Slang IR 指令集、解读 opcode 溯源列

Slang IR 参考索引导航:按家族检索 Slang IR 指令集、解读 opcode 溯源列

编译器图形学编程语言 【免费下载链接】slang Making it easier to work with shaders 项目地址: https://gitcode.com/GitHub_Trending/sl/slang 点击查看 免费下载 本指南围绕 Slang 编译器的 IR 指令参考文档子树(docs/generated/design/ir-referenc…

2026/10/12 1:37:53 阅读更多 →
一条命令让 AI Agent 具备逆向工程能力:REA 快速上手

一条命令让 AI Agent 具备逆向工程能力:REA 快速上手

一条命令让 AI Agent 具备逆向工程能力:REA 快速上手 【免费下载链接】rea Reverse engineer anything with agents, from app behavior down to native binaries. 项目地址: https://gitcode.com/GitHub_Trending/rea2/rea REA(Reverse Engineer…

2026/10/12 1:36:52 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →