分布式锁的几种实现方案与常见陷阱

举报
yd_268144123 发表于 2026/11/12 09:56:07 2026/11/12
【摘要】 一、为什么需要分布式锁单机多线程用 synchronized / Lock 就能互斥。但服务一旦部署多实例、或多台机器共享同一份资源(库存、账户余额、定时任务),本地锁就失效了——因为锁只在单个进程内有效。分布式锁要保证:同一时刻,跨进程/跨机器,只有一个持有者能操作共享资源。实现上有几种主流方案,各有取舍。 二、基于 Redis 的分布式锁最常见的做法,用 SET key value N...

一、为什么需要分布式锁

单机多线程用 synchronized / Lock 就能互斥。但服务一旦部署多实例、或多台机器共享同一份资源(库存、账户余额、定时任务),本地锁就失效了——因为锁只在单个进程内有效。

分布式锁要保证:同一时刻,跨进程/跨机器,只有一个持有者能操作共享资源。实现上有几种主流方案,各有取舍。

二、基于 Redis 的分布式锁

最常见的做法,用 SET key value NX PX ttl 原子地“不存在才设置 + 带过期时间”:

SET lock:order:123 <token> NX PX 30000
  • NX:键不存在才设置(保证互斥)。
  • PX 30000:30 秒自动过期(防止持锁者宕机导致死锁)。
  • value 用唯一 token(如 UUID),释放时校验是自己的锁才删。

释放锁必须用 Lua 脚本保证“校验 + 删除”原子:

if redis.call("get", KEYS[1]) == ARGV[1] then
  return redis.call("del", KEYS[1])
else
  return 0
end

坑一:锁过期但业务没跑完。业务执行时间超了 TTL,锁自动释放,别人拿到锁 → 并发问题。解决:用看门狗(后台线程定期续期,如 Redisson 的 watchdog),或合理评估并设置足够长的 TTL。

坑二:主从切换丢锁。主节点写入的锁还没同步到从库就宕机,主从切换后锁丢失。更强一致可用 RedLock(多节点多数派加锁),但 RedLock 本身也有争议,需权衡。多数业务用单节点/哨兵 + 看门狗已足够。

三、基于数据库的分布式锁

  • 唯一索引:用一张锁表,对资源 id 建唯一索引,插入成功即获锁,删除即释放。简单可靠,但 DB 压力大、性能一般,适合低频场景。
  • SELECT ... FOR UPDATE:行锁,事务内互斥,注意必须走索引否则会锁全表;且锁跟随事务,事务结束自动释放。

数据库方案不依赖额外组件,一致性由 DB 保障,但吞吐低,不适合高并发抢锁。

四、基于 ZooKeeper / etcd 的分布式锁

利用临时顺序节点:在锁节点下创建临时有序子节点,序号最小的持有锁;释放时删除自己节点,后一个监听前一个节点。

优点:

  • 会话机制天然防死锁:客户端断连后临时节点自动删除。
  • 强一致,适合对一致性要求高的场景(如选主、配置协调)。

缺点:依赖 ZK/etcd 集群,运维成本高;性能不如 Redis。

五、三种方案怎么选

方案 性能 一致性 复杂度/运维 典型场景
Redis 高 最终一致(单节点+看门狗够用) 低 大多数互联网业务抢锁
数据库 低 强(由 DB 事务保证) 低(已有 DB) 低频、强一致的小场景
ZK/etcd 中 强 高 选主、协调、强一致场景

原则:优先 Redis(配合看门狗 + token 校验),一致性要求极高再考虑 ZK/etcd,简单低频场景直接用数据库唯一索引。

六、通用正确性要点

  1. 加锁与过期必须原子(Redis 用 SET NX PX 一条命令,别拆成先 set 再 expire)。
  2. 释放必须校验持有者(token),避免误删别人的锁。
  3. 设置合理 TTL + 续期机制,防死锁也防“锁提前过期”。
  4. 加锁失败要有降级/重试策略:立即返回失败、自旋重试还是排队等待,按业务定。
  5. 锁粒度尽量小:锁到具体资源 id,而不是全局一把大锁,减少争用。

七、常见坑

  1. 业务超时 > 锁 TTL,导致并发进入(最经典)。
  2. 释放锁不校验 token,删掉了别人的锁。
  3. 把 setnx 和 expire 分开调用,中间崩溃就死锁。
  4. 重入问题:同一线程重复加锁要能重入(Redisson 的可重入锁按线程计数),自己实现的要留意。
  5. 主从架构下的锁丢失,对强一致场景不够安全。
  6. 锁范围内做耗时操作(远程调用、大事务),拖长持锁时间放大风险。

八、总结

分布式锁的核心目标是跨进程互斥。工程上最实用的组合是:Redis SET NX PX + 唯一 token + Lua 校验释放 + 看门狗续期,能覆盖绝大多数业务;数据库唯一索引适合低频强一致的小场景;ZK/etcd 用于选主等强一致协调场景。真正决定成败的往往不是选哪个组件,而是TTL、续期、token 校验、锁粒度这些细节是否处理到位。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。