真实面经题目 · 原创解析
ZooKeeper 实现分布式锁的原理是什么?
这题考察临时顺序节点、前驱监听、会话语义和异常重试流程,重点是说明为什么相对公平且能避免惊群。
真实面经题目 · 原创解析
这题考察临时顺序节点、前驱监听、会话语义和异常重试流程,重点是说明为什么相对公平且能避免惊群。
ZooKeeper 分布式锁通常在固定锁目录下创建临时顺序节点。客户端创建节点后读取 children 并排序,如果自己的序号最小就获得锁;否则只监听前一个序号节点。前驱节点删除后收到 watcher 通知,再重新读取 children 判断自己是否最小。锁释放是删除自己的临时节点;客户端崩溃或会话过期时临时节点自动删除。这个方案靠顺序节点形成排队,靠监听前驱减少惊群,靠会话语义处理客户端故障,但仍要处理连接断开、创建成功响应丢失、watcher 一次性触发和业务侧 fencing。
每个客户端在锁目录下创建 `lock-0000001` 这类临时顺序节点,序号由 ZooKeeper 分配,天然形成先后顺序。序号最小者进入临界区。
如果自己不是最小节点,就找到比自己小的最大节点并 watch 它。前驱删除时只唤醒一个后继,避免所有等待者同时被唤醒。
Watcher 是一次性的,而且通知只代表前驱发生变化,不代表自己已经获得锁。正确流程是收到通知后重新读取 children、排序、判断自己是否最小。
短暂连接断开不一定释放锁,session timeout 后临时节点才会删除。业务执行时间、GC STW 和网络隔离都可能影响锁持有安全,要设置合理会话超时。
创建节点成功但响应丢失时,客户端应按请求 GUID 或节点前缀查找自己已创建的节点,避免重复入队。强写入场景同样可以配 fencing token 防旧会话继续写。
这样每次释放锁只唤醒下一个候选者,减少惊群,并保持按顺序节点排队的公平性。
不会。只有会话过期后临时节点才删除。短断线期间客户端可能还持有锁,这也是设置 session timeout 和业务超时的原因。
不能。Watcher 一次性触发且可能合并事件,收到通知后必须重新查询 children 判断自己是否最小。
ZK 更强调一致性、排队和会话语义,适合强协调;Redis 更轻量、性能高,但主从切换和租约安全要额外处理。