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