面试知识库
极高 进阶

分布式锁方案对比#

一句话答案#

Redis 锁(高性能/主从可能丢锁)、ZK 锁(强一致/性能一般)、DB 锁(简单/性能差),生产推荐 Redisson。

核心要点

方案性能可靠性实现复杂度
Redis高中(主从不一致)低
Zookeeper中高(CP)中
etcd中高(CP, Raft)中
数据库低高低

生产推荐: Redisson(Watch Dog续期+可重入+公平锁);需要防旧持有者写入时用 RFencedLock(fencing token)。Redisson 官方已把 RedissonRedLock 标为 deprecated

面试回答(2分钟版)

分布式锁主要有三种方案。Redis锁性能最高,核心命令是SET key value NX EX实现原子加锁和过期,但存在主从切换时锁丢失的风险,因为主节点加锁成功后异步复制到从节点之前如果主挂了,新主上没有锁信息。ZooKeeper锁基于临时顺序节点实现,客户端创建临时顺序节点并Watch前一个节点,前一个节点删除时获得锁,天然是公平锁(可重入由客户端实现,如 Curator 的 InterProcessMutex),可靠性高因为ZK是CP系统,但会话超时(如长 GC)后锁会被释放,同样不是绝对安全,但性能一般因为每次加锁都要写入和同步。数据库锁最简单,通过唯一索引INSERT成功表示获取锁,但性能最差。生产环境我推荐用Redisson客户端,它封装了Watch Dog机制(仅在不指定 leaseTime 时生效,默认锁超时 30 秒,每 10 秒续期)防止业务没执行完锁就过期,支持可重入锁、公平锁、读写锁。对于Redis主从丢锁的问题,RedLock方案需要向N个独立Redis节点加锁获得多数才算成功,但Martin Kleppmann和Antirez有过争论:Kleppmann 认为 RedLock 依赖时钟和进程暂停的时间假设,且不提供 fencing token,GC 停顿后旧持有者仍可能写入;Redisson 官方已废弃 RedLock,改推 RLock 和 RFencedLock。实际中更实用的做法是业务层做幂等或版本号校验兜底。

追问与易错

追问方向:

  • “Redis 主从切换时锁丢失怎么办?”→ RedLock 方案向 N 个独立 Redis 加锁多数成功才算获取;更实用的做法是业务层做幂等兜底,评估锁丢失的业务影响是否可容忍
  • “ZK 分布式锁怎么实现的?”→ 客户端在锁节点下创建临时顺序节点,判断自己是否最小节点(是则获锁),否则 Watch 前一个节点的删除事件,天然公平锁且客户端断连自动释放
  • “RedLock 争议的核心是什么?”→ Kleppmann 指出:客户端拿锁后若发生长 GC/时钟跳变,锁过期被别人拿走,旧客户端醒来仍会写;RedLock 没有单调递增的 fencing token,存储端无法拒绝旧请求。Antirez 反驳说可以靠检查锁有效期缓解。结论:需要正确性的场景用带 fencing token 的锁(ZK zxid/etcd revision/Redisson RFencedLock),并让存储端校验 token
  • “分布式锁的粒度怎么设计?”→ 粒度越细并发越高但复杂度越大,通常按业务维度设计(如按订单 ID 粒度而非全局锁),避免锁竞争过大导致性能瓶颈

易错点:

  • ❌ “Redis 分布式锁绝对安全”——主从切换可能丢锁,需要评估业务容忍度
  • ❌ “加了分布式锁就万事大吉”——还要考虑锁粒度/过期时间/业务幂等