分布式组件【ZooKeeper】
文章目录
- 什么是ZooKeeper?
- 核心概念
- 数据模型:ZNode
- 监听机制:Watcher
- 会话机制
- 典型应用场景
- 1. 配置管理
- 2. 服务注册与发现
- 3. 分布式锁
- 4. Master选举
- 工作原理
- 集群架构
- ZAB协议
- Java客户端示例
- 常见问题
- 为什么集群要部署奇数个节点?
- ZooKeeper、Nacos和Eureka的区别?
- 总结
什么是ZooKeeper?
ZooKeeper是Apache旗下的一个开源项目,它为分布式应用提供高性能的协调服务。简单来说,ZooKeeperky可以管理分布式系统,负责维护配置信息、命名服务、提供分布式同步以及提供组服务等功能。
核心概念
数据模型:ZNode
ZooKeeper采用了类似文件系统的树形结构来组织数据,每个节点称为ZNode。这种设计非常直观,就像我们在电脑上管理文件一样。
ZNode有几种类型:
持久节点:创建后会一直存在,除非主动删除。适合存储一些持久化的配置信息。
临时节点:与客户端会话绑定,会话结束节点就会被自动删除。这个特性非常适合用来做服务注册与发现,一旦服务挂了,对应的节点就自动消失了。
顺序节点:ZooKeeper会自动在节点名称后面追加一个递增的序号。这个特性可以用来实现分布式锁和队列。
监听机制:Watcher
ZooKeeper提供了一个强大的监听机制。客户端可以在某个ZNode上注册Watcher,当这个节点发生变化时(数据修改、节点删除、子节点变化等),ZooKeeper会主动通知客户端。这个机制让应用能够实时感知到配置变更或者集群状态的变化,无需不断轮询,大大提高了效率。
会话机制
客户端与ZooKeeper服务器建立连接后会创建一个会话(Session)。会话有超时机制,如果客户端在超时时间内没有与服务器通信,服务器就会认为客户端已经挂了,从而清理该会话相关的临时节点。
典型应用场景
1. 配置管理
在微服务架构中,配置管理是个令人头疼的问题。将配置信息存储在ZooKeeper中,各个服务节点通过Watcher机制监听配置变化,就能实现配置的集中管理和动态更新。不用再一台台机器去修改配置文件,然后重启服务了。
2. 服务注册与发现
服务提供者启动时,在ZooKeeper上创建一个临时节点来表示自己可用。服务消费者通过监听这些节点的变化,就能实时获知有哪些服务可用。当某个服务节点挂掉后,对应的临时节点会自动删除,消费者立即就能感知到。
3. 分布式锁
利用ZooKeeper的顺序临时节点,可以很容易实现分布式锁。每个客户端尝试创建一个顺序节点,序号最小的客户端获得锁。其他客户端监听前一个节点的删除事件,当前面的节点被删除(即前面的客户端释放了锁)时,自己就可以尝试获取锁了。
4. Master选举
在主从架构中,多个节点竞争创建一个临时节点,创建成功的就成为Master。其他节点监听这个节点,一旦Master挂掉,临时节点被删除,其他节点重新竞争,完成Master的自动切换。
工作原理
集群架构
ZooKeeper本身也是一个分布式系统,通常以集群方式部署。集群中有一个Leader节点和多个Follower节点。
所有的写请求都会转发到Leader节点处理,Leader负责协调事务的提交。读请求则可以在任意节点上处理,这样可以提高读取性能。
ZAB协议
ZooKeeper使用ZAB(ZooKeeper Atomic Broadcast)协议来保证分布式数据一致性。简单来说,ZAB协议确保了所有写操作都会在集群中的多数节点上达成一致,从而保证数据的可靠性。
即使集群中少数节点故障,只要多数节点存活,ZooKeeper就能正常工作。这也是为什么ZooKeeper集群通常部署奇数个节点的原因——既能提供容错能力,又不会浪费资源。
Java客户端示例
public class ZooKeeperDemo {private static final String CONNECT_STRING = "localhost:2181";private static final int SESSION_TIMEOUT = 5000;public static void main(String[] args) throws Exception {ZooKeeper zk = new ZooKeeper(CONNECT_STRING, SESSION_TIMEOUT, event -> System.out.println("事件:" + event));// 创建节点String path = zk.create("/myapp", "hello".getBytes(), ZooDefs.Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);System.out.println("创建节点:" + path);// 读取数据byte[] data = zk.getData("/myapp", false, null);System.out.println("读取数据:" + new String(data));// 更新数据zk.setData("/myapp", "world".getBytes(), -1);// 删除节点zk.delete("/myapp", -1);zk.close();}
}
常见问题
为什么集群要部署奇数个节点?
ZooKeeper采用过半机制,即需要超过半数节点存活才能提供服务。3个节点最多允许1个故障,4个节点也是最多允许1个故障,容错能力相同,但4个节点成本更高。所以通常选择奇数个节点。
ZooKeeper、Nacos和Eureka的区别?
在微服务领域,这三个组件经常被拿来比较。它们都能实现服务注册与发现,但设计理念和特性各有不同:
一致性保证方面:
- ZooKeeper遵循CP原则(强一致性),采用ZAB协议保证数据一致性。当集群中超过半数节点故障时,整个集群将不可用。在网络分区的情况下,ZooKeeper会牺牲可用性来保证一致性。
- Eureka遵循AP原则(高可用性),即使所有Eureka Server都挂了,客户端也能从本地缓存中获取服务列表继续工作。Eureka更关注可用性,允许一定程度的数据不一致。
- Nacos支持CP和AP两种模式。对于临时实例使用AP模式(类似Eureka),对于持久化实例使用CP模式(类似ZooKeeper)。这种灵活性让Nacos可以根据不同场景选择合适的策略。
功能丰富程度:
4. ZooKeeper是一个通用的分布式协调服务,服务注册发现只是它的一个应用场景。它还可以做分布式锁、配置管理、Master选举等,但使用起来需要自己封装,相对复杂。
5. Eureka专注于服务注册与发现,功能相对单一。它是Spring Cloud体系的一部分,与Spring Boot集成非常方便。但Eureka只负责服务发现,配置管理需要结合Spring Cloud Config等其他组件。
6. Nacos既支持服务注册发现,又支持配置管理,还提供了友好的控制台界面。可以说是"一站式"解决方案,开箱即用,对国内开发者特别友好(阿里巴巴开源,中文文档完善)。
性能与扩展性:
- ZooKeeper的写性能受限于Leader节点,写操作需要过半节点同步确认,延迟相对较高。但对于不频繁变更的配置数据来说,这不是问题。
- Eureka的设计非常轻量,性能很好,适合大规模服务集群。但Eureka 2.x已经停止维护,后续发展存在不确定性。
- Nacos在性能上做了很多优化,支持十万级服务实例,同时提供了丰富的扩展能力。而且Nacos社区活跃,版本迭代快。
总结
说了这么多,咱们来总结一下ZooKeeper到底是个什么东西。
ZooKeeper的本质核心原理其实也不复杂:ZooKeeper用一个叫ZAB的协议保证数据在集群里保持一致。简单说就是有一个Leader节点负责协调,其他Follower节点跟着它走。这就是为什么ZooKeeper能保证强一致性,但也因此在网络分区时可能会暂时不可用。
使用场景主要有这么几个:
一是配置管理,把配置放ZooKeeper里,所有服务都从这儿读,改一次就全生效,省得一台台机器去改。
二是服务注册发现,服务启动时在ZooKeeper上留个临时节点,挂了自动消失,其他服务就能实时知道哪些兄弟还活着。
三是分布式锁,多个进程抢同一个资源时,通过ZooKeeper来排队,谁拿到锁谁干活,井然有序。
四是Master选举,几台机器抢着创建一个节点,创建成功的就是老大,老大挂了大家重新选,自动化得很。