Zookeeper 是干什么的?

#中间件#面试八股

Zookeeper 是干什么的?

结论先行:ZooKeeper(ZK)是一个高可用的分布式协调服务,用“类文件系统的树形命名空间 + 节点监听 + 会话”这三样原语,让分布式系统能就“谁活着、谁当主、配置是什么、锁在谁手里”达成一致。它不存业务数据,只存协调元数据。

一、它提供的四样原语

原语含义用途
节点(znode)路径唯一的树形数据节点,可带版本命名、配置、元数据
监听(watch)对节点变更的一次性订阅通知、服务发现
会话(session)客户端与集群的临时身份,带超时存活探测、临时节点自动清理
顺序号(sequential)父节点下自增序号队列、分布式锁排队

二、集群角色与写路径

            ┌──────────┐
   写请求 → │  Leader  │ ── 提案 → 事务日志 → 广播给 Follower
            └────┬─────┘
        ┌────────┴────────┐
   ┌────▼────┐       ┌────▼────┐      ┌──────────┐
   │Follower │       │Follower │      │ Observer │
   └────┬────┘       └────┬────┘      └────┬─────┘
        └──────── 过半 ACK 才算成功 ────────┘
                    读请求可就地返回

Leader 统一处理写,Follower 参与投票与读,Observer 只读不投票,用来扩展读能力而不拖慢写性能。

三、最小可用示例

# 启动单机(开发环境)
bin/zkServer.sh start

# 常用命令
create /app "root"                 # 持久节点
create -e /app/lock "holder"       # 临时节点,会话结束即删
create -s /app/task "job-"         # 顺序节点,自动补 10 位序号
get /app
set /app "v2"
ls /app
delete /app/lock

Java 侧一般用 Apache Curator 封装,避免自己处理重连与重注册:

CuratorFramework client = CuratorFrameworkFactory.newClient(
        "127.0.0.1:2181", new ExponentialBackoffRetry(1000, 3));
client.start();
client.create().withMode(CreateMode.EPHEMERAL).forPath("/app/inst-1", "10.0.0.1".getBytes());

四、它不擅长什么

场景原因
存大对象单节点默认上限 1MB,超过影响同步性能
高频写每次写都要过半确认 + 落盘事务日志,QPS 有限
当数据库用无查询、无索引、无事务回滚,只适合元数据
大规模临时节点数十万临时节点时,会话超时清理会造成尖峰

五、与其他协调组件的定位

组件一致性协议数据模型典型使用者
ZooKeeperZAB树形 znodeDubbo、HBase、Kafka 旧版
etcdRaft扁平 KVKubernetes
ConsulRaftKV + 服务目录多语言微服务

三者都能做“注册 + 配置 + 选主”,差别在生态与数据模型,不在能力有无。

常见追问

  • 追问:ZK 和 etcd 有什么区别?etcd 用 Raft,接口是 KV + watch,云原生生态更好;ZK 用 ZAB,树形模型与顺序节点对“排队锁”更自然。
  • 追问:ZK 为什么要求奇数节点?quorum 需要过半,偶数节点并不增加容错能力,只增加成本。
  • 追问:ZK 挂了业务会立刻不可用吗?不会立刻,客户端有本地缓存与重连;但无法注册新实例、无法感知下线,属于“降级可用”。

小结

  • ZK 是协调服务,四样原语是 znode、watch、session、顺序号。
  • 写走 Leader + 过半确认,读可就地返回,Observer 扩展读。
  • 单节点 1MB、写 QPS 有限,别把它当存储用。
  • 生产上用 Curator,别手写重连与重注册逻辑。
笔记加载中…