bigywater.tech
ZooKeeper · 21

批量写入与单次写入对比

ZooKeeper 的 multi(事务)不只是为了原子性,它还是批量写入最有效的办法。这篇量一下 100 次 create 逐个提交和一次 multi 提交的差别,再验证它的原子性、zxid 和 check 条件。

48 倍
100 次 create:逐个同步 vs 一个 multi(单机)
1 个 zxid
multi 里的所有操作共用同一个事务号
约 1 MiB
multi 整个请求的大小上限

速度

实测 · 本机执行输出
  逐个 create 100 次:  297.9 ms(2.98 ms/个)
  一个 multi 含 100 个 create:    6.2 ms(0.06 ms/个)  → 快 48 倍

差别主要来自每次写都要等事务日志 fsync(第 55 篇)。如果用异步 API 流水线提交,也能接近这个速度(第 1 篇量到异步写 1 万次/秒),区别是 multi 还保证原子性。

原子性

实测 · 本机执行输出
  commit 返回 [RolledBackError(), RolledBackError(), NodeExistsError(), RuntimeInconsistency()]
  之后 /at 的子节点: [] (a、b 也没有被创建)
  不抛异常的写法 commit() 返回的结果列表: ['RolledBackError', 'NodeExistsError']

zxid 与 check

实测 · 本机执行输出
  5 个 create 的 czxid: ['0x209', '0x209', '0x209', '0x209', '0x209'] 全部相同: True
  版本一致时 commit → [True, '/derived']
  /cfg 被改过之后 commit → ['BadVersionError', 'RuntimeInconsistency'] | /derived2 存在: False

大小限制

实测 · 本机执行输出
  30 个各 50000 字节的 create(合计约 1.5 MiB)一次提交 → ConnectionLoss

分步演示

multi 事务
本步的对象

    本文用到的工具与边界

    • 本机 macOS 27 / ZooKeeper 3.9.6(brew 安装的 jar,用 java -cp 直接启动自己的实例,OpenJDK 17 Temurin,JVM 堆 128 MiB)/ 本机回环端口 7300+,数据在临时目录;默认 tickTime=2000;计时用 time.perf_counter,数字每次运行会有小幅抖动。单机;kazoo 的 transaction();耗时是 5 次重复的中位数
    • 没有验证:集群里 multi 的耗时、multi 里操作数量的上限、setData / delete 在 multi 里的行为、multi 失败时的 watch 触发、Java 客户端的 Op 与 multi API 差别
    京ICP备2026067502号-1京公网安备11010502063487号