1. 核心概念
- 命名服务 (Naming Service):在分布式系统中,通过一个易记的名称(Name)来获取资源或服务的地址、元数据等信息。类似于 DNS 将域名解析为 IP,ZooKeeper 将服务名解析为服务地址列表。
- 配置管理 (Configuration Management):集中管理集群中所有节点的配置信息,并确保当配置发生变更时,所有节点能实时感知并更新,实现“配置热更”。
2. 原理与实现
2.1 命名服务 (Naming Service)
ZooKeeper 的命名服务主要依赖其 树形分层结构(Hierarchical Namespace)。
- 实现方式:
- 通常在
/services根节点下创建服务名节点,例如/services/user-service。 - 服务提供者启动时,在
/services/user-service下创建子节点(通常是临时节点),节点名为 IP:Port 或 UUID,节点数据包含具体的服务地址。 - 服务消费者读取
/services/user-service的所有子节点,获取可用服务列表。
- 通常在
- 优势:
- 解耦:消费者只需知道服务名,无需硬编码 IP。
- 动态性:利用临时节点,服务下线自动剔除。
2.2 配置管理 (Configuration Management)
ZooKeeper 的配置管理主要依赖其 数据存储 和 Watch 机制。
- 实现方式:
- 存储配置:将公共配置(如数据库连接串、开关配置)写入一个 ZNode,例如
/configs/db-config。 - 获取配置:应用启动时,读取该 ZNode 的数据,并加载到内存中。
- 注册监听:应用在读取数据的同时,对该 ZNode 注册一个 DataChanged Watch。
- 动态更新:当管理员修改了
/configs/db-config的数据,ZooKeeper 服务端会向所有注册了 Watch 的客户端发送通知。 - 重新拉取:客户端收到通知后,再次读取 ZNode 的最新数据并更新本地配置。
- 存储配置:将公共配置(如数据库连接串、开关配置)写入一个 ZNode,例如
- 源码关键点:
getData(path, watch):读取数据并注册监听。process(WatchedEvent):回调接口,处理配置变更通知。
3. 性能与可靠性考量
- 数据大小限制:ZooKeeper 的 ZNode 默认限制存储 1MB 数据。因此,它适合存储元数据或关键配置,不适合存储大文件(如图片、大段文本)。如果配置过大,建议存储在数据库或对象存储中,ZK 只存版本号或索引地址。
- 读多写少:配置管理是非常典型的“读多写少”场景,非常契合 ZooKeeper 的性能特性(Follower 处理读,Leader 处理写)。
- 容灾:配置中心通常是单点依赖,ZooKeeper 集群的高可用性保证了配置服务不会轻易宕机。
4. 总结
面试官:什么是 ZooKeeper 的命名服务和配置管理?
候选人: 命名服务是利用 ZooKeeper 的树形目录结构,为分布式系统中的资源提供统一的名称标识。最典型的例子是 RPC 注册中心,服务提供者在 ZK 中创建节点,消费者通过节点路径获取服务地址,实现了服务地址的解耦和动态发现。
配置管理则是利用 ZooKeeper 的数据存储加 Watch 机制。我们将配置信息存储在 ZNode 中,所有客户端监听这个节点。一旦配置发生变更,ZK 会通知所有客户端,客户端收到通知后主动拉取最新配置,从而实现了配置的集中管理和动态热更新。
需要注意的是,ZK 适合存储小量的关键配置(默认 1MB 上限),适用于读多写少的场景。