ZooKeeper:排障、恢复与场景自检
ZooKeeper 会话故障与权限排查
断连与过期
ZooKeeper 断连排查 先区分 Disconnected 与 Expired。前者检查网络、客户端到服务端的连接、服务端多数派以及暂停时间;后者明确旧会话所有权失效,需要新会话和重新竞争。不要仅调用 exists 确认路径还在,就让旧进程继续写资源:查询和写入之间仍有竞态,真正的 fencing 必须放在资源端。
客户端日志要记录协商的 session timeout、状态转换时间、session ID 的可脱敏标识以及最后成功操作。持续 GC 暂停、时钟测量错误或线程阻塞都可能把“网络断连”表象放大。会话超时调大只能改变检测与清理延迟,不能消除旧持有者恢复后的风险。
Watch 与读取
ZooKeeper Watch 丢通知 应先检查是否把一次性 watch 当成持久订阅、是否对不存在路径使用了 getData、是否在回调里做了长任务。正确修复是重读并重装 watch,以最新快照对账;不是要求服务端重放每一次 NodeDataChanged。业务确实需要每次事件时,应选持久事件日志系统,不能在协调服务回调上补一个内存计数器宣称不丢消息。
读取到新值后应用自己的缓存更新也应幂等,重复通知与重连对账都可能带来同一状态。需要读写顺序约束时,区分本客户端有序操作和其他客户端的观察;不能把任意服务端的普通读取都描述为最新全局快照。
权限与冲突
ZooKeeper BadVersion 排错 先核对用的是数据 version 还是 cversion/aversion,再确认节点是否删除重建。竞争写入时重新读取并重新计算,-1 是跳过版本条件,不能当通用重试参数。NoNode 应检查路径生命周期与父节点,NodeExists 应检查创建结果是否属于前一次超时后实际上已成功的请求,避免盲目重复创建顺序节点。
ZooKeeper NoAuth 权限 检查认证方案、用户名密码、当前 znode ACL 和所需操作位。ACL 不递归继承到后来创建的子节点,每次 create 都应显式选择权限。CREATOR_ALL_ACL 需要先认证;换身份重跑可能无法读取第一次创建的父节点,这是权限生效,不是应开放 world:anyone 的理由。digest 不加密传输,生产仍须考虑 TLS、凭据管理和审计。
备份恢复与练习
ZooKeeper 恢复边界 包括快照与事务日志、集群配置和客户端重建会话,不能只拷贝一个 znode 数据文本。恢复后需要重新确认临时节点所有者、应用缓存和外部资源 epoch;旧锁状态不能作为继续执行旧任务的凭据。本课程不提供恢复命令,避免在没有拓扑与版本前提时误删 dataDir。
练习:两个程序出现 BadVersion,一个同事把 expected version 改成 -1 后“成功”。参考解答:错误消失但并发保护被移除;恢复版本检查,并为业务更新定义合并或冲突反馈。另一题:日志中只有 Disconnected,能否宣称 session 未过期?答:不能,旧进程可能收不到及时通知,应暂停有所有权要求的工作并靠资源端拒绝陈旧写。
适用 3.9.x,核对 2026-10-17;依据官方 Programmer's Guide。全部故障均为理论推演,示例未执行。
ZooKeeper 协调协议自检
综合自检
ZooKeeper 综合自检 要能分别回答四个问题:连接是否活着,会话是否仍有效,节点数据是否仍为读到的版本,外部资源是否允许当前写入。它们不能互相替代。临时节点解决会话相关清理,CAS 解决单节点条件更新,watch 解决缓存失效提醒,fencing 解决旧持有者越权写外部资源;把任何一个描述成完整分布式锁都漏掉了合同。
场景与参考解答
ZooKeeper 并发推演:A 读版本 7,B 改为 8,A 用 7 更新;预期 A 得 BadVersion,并且不改变 B 的值。A 重新读 8 后,应结合业务重新计算,而非只换数字提交原内容。节点删除重建可能重新出现小版本,因此版本号不能离开 znode 生命周期单独成为全局 fencing token。
ZooKeeper 会话推演:A 持候选节点暂停,集群过期其会话,B 成为持有者并带 epoch=12 更新资源;A 恢复带 epoch=11 写入。参考解答:资源端必须原子拒绝 11;如果只是 A 检查本地 connected 布尔值,陈旧写仍可能发生。B 的新会话、节点序号与资源 epoch 的映射必须可审计,恢复和重建不能让 epoch 倒退。
第三题:watch 第一次回调后服务端又更新三次,客户端最终只读到末值,是否是错误?答案:对本课一次性 watch 合同不是错误。它承诺状态变更通知与读取协调,不承诺完整事件流;消费端要按快照恢复状态。如果业务审计要求每次配置变更都有一条记录,应另建持久变更历史。
阶段作业评分
ZooKeeper 设计复盘 要求画出创建父节点、读取 Stat、安装 watch、CAS 写入、重读重装、创建临时子节点、关闭会话七步。每步注明可能异常:NoNode、NoAuth、BadVersion、ConnectionLoss 或 SessionExpired。参考解法中,ConnectionLoss 后不能仅凭异常确定写入没有发生;应通过业务标识、节点读回或可幂等协议确认,不能直接无限重试顺序 create。
能解释三个不确定性才算完成:网络异常的结果不确定、通知到达不代表持有者资格、快照版本不代表外部资源授权。只记住 CLI 命令不等于理解协调协议。
已覆盖与未覆盖
本站交付的是会话、节点、条件更新、一次性 watch、ACL 和 fencing 的理论及独立 Java 源码。它不是生产锁库,没有实现前驱监听完整算法、只读模式策略、配额或动态重配置。所有示例未执行,未下载依赖、未编译 Java、未启动集群。选择生产方案前应在授权环境验证补丁版本、集群配置和故障时序。
版本族 3.9.x,核对日期 2026-10-17;官方 Recipes 用于进一步研究候选节点和前驱监听,Programmer's Guide 用于核对 API 合同。
继续阅读
- 完整实践
- 知识专题