bigywater.tech
ZooKeeper · 1

ZooKeeper 的定位与适用场景

ZooKeeper 常被叫做「分布式协调服务」,但它到底擅长什么、不擅长什么?这篇不讲概念,直接在自己起的 ZooKeeper 3.9.6 上量:数据大小的上限、读写速度的差别、顺序保证和内存里的树,再据此回答它的定位。

约 1 MiB
单个 znode 数据的上限:1023 KiB 成功,1024 KiB ConnectionLoss
19 倍
同步读与同步写的速度比(单机,本机回环)
全局递增 zxid
每个写事务一个编号,顺序在整个集群里只有一个答案

数据大小的上限

实测 · 本机执行输出
  创建     1 KiB 的 znode → OK
  创建   512 KiB 的 znode → OK
  创建  1000 KiB 的 znode → OK
  创建  1023 KiB 的 znode → OK
  创建  1024 KiB 的 znode → ConnectionLoss
  创建  2048 KiB 的 znode → ConnectionLoss

超过上限时,客户端得到的是 ConnectionLoss(连接被服务端断开),而不是一个「数据太大」的错误,排查时容易误判成网络问题。上限由 jute.maxbuffer 决定(第 24 篇)。

读写速度

实测 · 本机执行输出
  同步写 1000 次:    329 次/秒(3.04 ms/次)
  同步读 5000 次:   6361 次/秒(0.16 ms/次)
  异步(流水线)写 5000 次:  10574 次/秒

写必须先写事务日志再应用到内存,读只读内存。集群里写还要多数派确认(第 2 篇量了单机与 3 节点的写延迟差别)。所以 ZooKeeper 适合读多写少、数据小的场景:配置、成员列表、锁的状态——不适合存业务数据或做高吞吐写入。

顺序

实测 · 本机执行输出
  /o1 /o2 /o3 的 czxid: ['0x1778', '0x1779', '0x177a'] 严格递增: True
  zxid 从服务端怎么看(四字命令 srvr 里的 Zxid): 0x177a

一棵常驻内存的树

实测 · 本机执行输出
  znode 数 zk_znode_count = 6012 | 近似数据大小 zk_approximate_data_size = 3230728 字节 | zk_watch_count = 0

怎么定位它

综合上面四点:ZooKeeper 提供的是小块数据 + 全局顺序 + 通知(通知机制在第 15 篇)。它适合做配置中心、服务发现、分布式锁、选举这类「大家需要对少量状态达成一致」的事;不适合当数据库、缓存或消息队列。这个归纳来自上面的实测和后面章节,本文没有拿它去对比别的系统(第 108–110 篇再比较 etcd、Consul)。

分步演示

ZooKeeper 的边界
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / ZooKeeper 3.9.6(brew 安装的 jar,用 java -cp 直接启动自己的实例,OpenJDK 17 Temurin,JVM 堆 128 MiB)/ 本机回环端口 7300+,数据在临时目录;默认 tickTime=2000;计时用 time.perf_counter,数字每次运行会有小幅抖动。单个单机节点,默认 tickTime=2000;客户端用 kazoo 2.11.0;读写各跑一次
    • 没有验证:集群里的写延迟(第 2 篇)、watch 通知的延迟与数量上限(第 15、17 篇)、多客户端并发写的吞吐、更大的 jute.maxbuffer 设置、SSD 与机械盘的差别
    京ICP备2026067502号-1京公网安备11010502063487号