概述
zookeeper 属于 apache hadoop 的一个子项目,是一个分布式的协调中间件,用于统一配置管理、统一命名服务、分布式锁、集群管理等。
zookeeper本身属于一个分布式服务,只要半数以上节点存活,就能工作。
zookeeper 原理
简单的来说,zookeeper = 文件系统 + 通知机制。
文件系统
zookeeper的数据结构类似于linux的文件系统,每个子目录为一个znode,通过路径来标识,这个路径名就是znode的key。
znode是可以存储数据的,可以自由的增加和删除znode,也可以在一个znode上创建子znode。
znode节点
- 临时节点:当客户端和zookeeper连接断开时,客户端创建的临时节点会被删除。
- 持久节点:和临时节点不同,持久节点不会被zookeeper自动删除。
- 带序号节点:临时节点和持久节点都可以设置带序号,zookeeper会自动为节点分配一个递增的序号。
通知机制
zookeeper提供监听器,监听目标节点发生变化(数据改变、被删除、子目录节点增加删除)时,通知客户端变化结果。
客户端可以调用zookeeper的监听接口,阻塞等待节点的变化。
zookeeper 集群
zookeeper集群最低要包含2台机器,通过zab协议实现选举和数据的一致性。
zookeeper集群的每个节点,对客户端来说数据模型都是一样的,读写请求发给任意一个节点都一样。
角色
- leader:只能有一个节点,由集群选举产生,提供读写服务。
- follower:提供读服务,转发写请求给leader,可以参与选举。
- observer:观察者,提供读服务,转发写请求给leader,不参与选举。
leader同步写操作时要等待所有follower确认,follower节点太多会造成写入性能较差,但有时候为了缓解读压力,又需要增加节点,为了不能增大写的压力,采用observer,由于不参与选举,对observer扩容时不会导致写压力增大。
一致性实现
- 写操作:所有写请求转发给master,leader写本地,并广播给所有follower,超过一半响应成功时,则响应客户端成功。
- 读操作:follower可以直接返回,读到的数据可能不是最新数据,客户端可调用sync方法获取最新数据。
- 最终一致性:由于可能会读到旧数据(少于1半节点),读写只保证最终一致性。
- 顺序一致性:客户端调用顺序和写入顺序一致,利用写入的顺序一致性,客户端可以基于zk的分布式锁实现强一致性业务。
性能分析
- 读性能好:zookeeper的节点数据是保存到内存的,读性能非常高。
- 写性能一般:写入耗时约50ms,写操作需要同步给所有follower并等待确认,比较耗时。
- 选举流程耗时:选举流程通常耗时半分钟到2分钟,期间zookeeper没有leader,是不可用的。
应用场景
统一命名服务
就是服务发现,流程为
- 上下游服务之间约定好一个持久znode作为根节点。
- 下游服务启动后,在znode根节点下创建一个临时有序号的子znode,并写入自己提供的IP地址和端口。
- 上游服务监听znode根节点,当存在子node的创建(加入新服务)和删除(摘除服务),上游服务更新IP+端口列表。
统一配置服务
将配置保存到zookeeper的持久znode上,分布式各个服务统一监听配置节点,配置发生变化时,更新各自的配置。
集群管理
集群中常常需要实时了解其他节点的运行状态,比如leader选举,可以通过监听临时节点来实现。
leader选举
所有机器创建临时顺序编号目录节点,每次选取编号最小的机器作为leader就好。
监控其他机器退出
通过监听临时子目录的方式,可以监控其他机器的状态。
分布式锁
- 多个客户端同时向zookeeper的某个指定节点下创建临时节点(带序号),根据顺序一致性协议,序号id根据访问时间递增。
- 客户端创建临时节点后,获取所有节点的序号id,判断自己是否最小,如果是则表示得到了锁,使用完成后删除临时节点。
- 如果判断自己id不是最小值,则监听比自己小1的节点变化,当前一个客户端处理完成删除节点后,监听到后,得到锁。
consul对比
consul也是一款优秀的分布式协调中间件,二者的区别有
- consul支持健康检查,包括端口状态,内存使用等。
- consul支持多数据中心,跨机房。
- consul支持图形界面查看服务的运行情况。
- consul支持Restful接口,实现简单,而zookeeper客户端代码实现太复杂。