首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >分布式锁工程实践:Redis、ZooKeeper 与数据库锁的选型

分布式锁工程实践:Redis、ZooKeeper 与数据库锁的选型

原创
作者头像
PikeTalk
发布于 2026-10-16 19:38:02
发布于 2026-10-16 19:38:02
520
举报

先问要不要锁,再问用什么锁

分布式锁是并发控制的手段,不是目标。动手之前先确认:这个互斥能不能用「数据库唯一约束」「乐观版本号」「幂等设计」解决?能的话就不要引入锁——锁带来的是可用性依赖、续期复杂性、死锁风险三件套。只有在「多实例互斥执行一段非幂等逻辑」的真实需求下(定时任务防重跑、防止缓存击穿重建、库存防超卖兜底),分布式锁才是正确工具。一、三种实现的真实边界

  1. Redis(Redlock/单实例 SET NX PX):性能最好,主流选择。但要注意两个致命细节:一是锁必须带过期时间且值唯一(用 UUID+实例标识,释放时用 Lua 脚本校验删除,防止误删别人的锁);二是主从切换会丢锁——主节点写入锁后未同步就宕机,从节点升主,第二个客户端加锁成功,两个客户端同时持锁。Redlock 多数派方案能缓解但部署重、争议大(Martin Kleppmann 的批评值得读)。容忍极小概率互斥失效的互斥场景(如缓存重建)用 Redis 合适;资金类强互斥不要只靠 Redis;
  2. ZooKeeper/etcd:基于临时顺序节点 + watch,天生解决「持锁客户端挂了锁自动释放」(会话断开节点消失),互斥性强于 Redis。代价是性能低一个量级、集群运维成本高。适合锁竞争激烈、正确性优先的中间件类场景(选主、元数据互斥);
  3. 数据库锁:INSERT ... ON DUPLICATE KEY 或唯一索引 + GET_LOCK。最笨但最可靠——依赖已有的数据库高可用,无需新组件。低频互斥(分钟级定时任务防重)直接用数据库锁,别为了一个锁引入 Redis/ZK 依赖。

二、不管用哪种,这四个坑都要防

  1. 业务超时 > 锁过期:持锁方逻辑没执行完锁就过期了,第二个客户端进场。对策:看门狗续期(后台线程定期延长 TTL,如 Redisson 的 watchdog),并把业务超时设计得小于锁超时;
  2. 释放别人的锁:没有「值校验 + Lua 原子删除」的释放代码,在高并发下必然误删;
  3. 可重入:同一线程/同一事务内重复申请会死锁的,选择支持可重入的实现(Redisson、ZK 顺序节点);
  4. 锁粒度:锁「用户 ID」而不是锁「整张表」;锁 key 带上业务维度,把互斥范围压到最小。

三、选型决策树

资金/库存级强互斥 → 数据库唯一约束兜底 + Redis/DB 锁双保险;一般互斥(任务防重跑、缓存重建)→ Redis 单实例锁 + 看门狗 + 值校验释放;已有 ZK/etcd 且要求强互斥 → 直接用其锁实现;低频场景 → 数据库锁。

四、验收

锁做得对不对,用三个测试验证:持锁方执行超过 TTL 后不出现双执行(或双执行被兜底拦截);A 释放锁后 B 立即可获取;主从切换/客户端宕机后锁在预期时间内可被重新获取。通过这三关,锁才敢上生产。

分布式锁的工程真相:它不是保证 100% 互斥的银弹,而是把互斥失效概率压到业务可接受范围、并给每次失效准备好兜底手段的组合方案。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 先问要不要锁,再问用什么锁
  • 二、不管用哪种,这四个坑都要防
  • 三、选型决策树
  • 四、验收
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档