ZooKeeper 故障处理与注意事项

为了有效使用 ZooKeeper,需要了解 ZooKeeper 可能发生的故障种类及处理方式。

故障恢复

当客户端从 ZooKeeper 服务端获取响应时,可以肯定这个响应信息与其他响应信息能够保持一致性。而在连接丢失等无法保证一致性的情况下,客户端会使用 Disconnected 事件和 ConnectionLossException 异常来表示异常状态。

出现上述情况时,ZooKeeper 客户端会不断尝试连接到另一个 ZooKeeper 服务器,直到最终重新建立会话。会话重新建立会产生 SyncConnected 事件,开始处理请求,注册之前已经注册的监视点,并对失去连接这段时间的数据变更产生监视点事件。

如果发生异常时没有正在进行的请求,则对客户端几乎没有影响;如果存在正在进行的请求,就需要认真处理异常状况。

对于异常时正在进行的请求,比如 create 操作,客户端无法通过异常信息判断请求是否被处理,需要在重新建立连接后先获取节点状态,再根据节点状态选择是否重新执行 create 操作,而不能直接简单地重复操作。

故障导致 exists 监视点丢失事件

ZooKeeper 在故障重连后,对于数据没有发生变更的监视点会重新注册,对已经发生变化的节点产生监视点事件,但存在一种情况会错误监视点事件 —— exists 监视点。

exists 操作比较特殊,是对一个不存在的监视点设置监视点,如果在连接断开期间所监视的节点被创建然后删除,待重新连接后,没有发现这个节点,所以只是重新注册,并不会产生监视点事件。

因为这种特殊情况,所以要尽量避免监视一个 znode 节点的创建事件,如果一定要监视创建事件,应该尽量监视存活期较长的 znode 节点。

群首选举与外部资源

ZooKeeper 为所有客户端提供了系统的一致性视图,客户端与 ZooKeeper 的任何交互操作,ZooKeeper 都会保持同步,但 ZooKeeper 无法保护与外部设备的交互操作。

比如多个客户端通过群首选举让主节点持有外部资源的情况:客户端 A 首先称为主节点持有节点,但因为线程调度等原因(比如持续较长时间的垃圾回收),ZooKeeper 判断与 A 会话中止,重新选举客户端 B 为主节点并持有外部资源,待 A 恢复正常时发送已经队列化的更新到外部资源,损害系统状态。

为了解决上述问题,可以尽量确保应用不会在超载或时钟偏移的环境中运行,另外可以通过 ZooKeeper 来扩展对外部设备协作的数据,比如使用隔离符号。简单的隔离符号比如 只有持有最新符号的客户端才能访问资源,对外部资源进行访问时,客户端需要提供隔离符号,如果外部资源在之前已经接收过更高版本的符号,访问就会被拒绝。

数据字段和子节点限制

ZooKeeper 默认对数据字段的传输限制为 1MB,该限制为任意节点数据的最大存储字节数,同时也限制任意父节点可以拥有的子节点数。

ZooKeeper 默认的限制值已经足够大,需要避免接近该限制值的使用。如果有特殊用途可以通过修改配置调整限制值。

打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • © 2016-2020 姜越

谢谢老板

支付宝
微信