一个节点上挂了几百上千个 watcher,它一变化,所有人同时收到通知又同时去读——这就是 Watcher 风暴(惊群)。这篇在 300 个客户端的规模上量通知扇出的时间和惊群时服务端的负载。
wchs: 300 connections watching 1 paths Total watches:300 mntr zk_watch_count = 300 | zk_num_alive_connections = 302
set 调用自己用时 46.2 ms;300/300 个收到通知:第一个 5 ms、中位 42 ms、最后一个 51 ms 1 个 watcher:通知在 set 开始后 6.1 ms 到达
300 个客户端并发重新读取 + 注册 watch 共用 91 ms;单次 get 延迟(客户端侧)中位 11.2 ms、最大 28.9 ms;服务端 zk_max_latency = 1 ms
规模放大后(几千到几万个 watcher)才会成为问题。常见的缓解办法:让 watcher 只监听必要的节点、用「一个监听者 + 本地广播」代替每个客户端各自 watch、在重读前加随机延迟。这些办法本文没有实验验证。