0. Overview
1. 用途
- 集群管理
- 集群机器监控/负载均衡
- 集群选主
- 配置管理
- 命名服务
- 分布式锁
- 队列管理
2. 特点
3. 基本架构
- zk角色
- zk消息类型
- Znode类型
4. 数据读写
5. 工作原理
- Zab协议/数据更新
- Fast Paxos协议/Leader选举
- Server的三种状态
- Watcher机制
6. Reference
Zookeeper主要是一个分布式服务协调框架
,实现同步
服务,配置维护
和命名服务
等分布式应用,基于对Zab协议(ZooKeeper Atomic Broadcast,zk原子消息广播协议,分布式一致性算法)的实现,能够保证分布式环境中数据的一致性。
简单来看,zookeeper=文件系统+通知机制。
/clusterServersStatus/{hostname}
分布式系统都有好多机器,比如在搭建hadoop的HDFS时,需要在一个主机器上(Master节点)配置好HDFS需要的各种配置文件,然后通过scp命令把这些配置文件copy到其他节点上,这样各个机器拿到的配置信息是一致的,才能成功运行起来HDFS服务。但是这里有个很致命的缺陷,特别对于在线服务的重启,假设线上server有1000台,那么如果不能同一时刻将新配置都同步,那么很可能会造成1000台中前500台是新配置,而后500台还是旧配置。
zk.exist("/app1",true)
,并且实现回调方法Watcher。那么在zk上/app1 znode节点下数据发生变化的时候,每个机器都会收到通知,Watcher方法将会被执行,那么应用再取下数据即可zk.getData("/app1",false,null)
zk configuration management
zk提供了这样的一种服务:一种集中管理配置的方法,我们在这个集中的地方修改了配置,所有对这个配置感兴趣的都可以获得变更Watcher。这样就省去手动拷贝配置了,还保证了可靠和一致性。
例如,QConf的应用,
分布式环境下,经常需要对应用/服务进行统一命名,便于识别不同服务。可以简单理解为一个电话薄,电话号码不好记,但是人名好记,要打谁的电话,直接查人名就好了。类似于域名与ip之间对应关系,域名容易记住。
单机程序的各个进程对互斥资源
进行访问时需要加锁,那分布式程序分布在各个主机上的进程对互斥资源进行访问时也需要加锁。
分布式系统可能会有多个可服务的窗口,但是在某个时刻只能让一个服务去工作,当这台服务出问题时锁要被释放,立即failover到另外的服务。这在很多分布式系统中都是这么做,这种设计有一个更好听的名字叫Leader Election
/选主
。
例如,到银行取钱,有多个服务窗口,但对你来说,只能有一个窗口对你服务,如果正在对你服务的窗口的柜员突然有急事走了?此时怎么办?找大堂经理(zookeeper)。大堂经理指定另外的一个窗口继续为你服务。
client-server architecture
zk的工作集群可以简单分成两类,一个是Leader,其余的都是Learner(follower和observer)
PING | 指Learner的心跳信息 |
---|---|
REQUEST | 指Follower发送的提议信息,包括写请求及同步请求 |
PROPOSAL | Leader发起的提案,要求Follower投票 |
ACK | 指Follower对提议的回复,若超过半数的Follower通过,则commit该提议 |
COMMIT | server最新一次提案的信息 |
UPTODATE | 表明同步完成 |
SYNC | 返回SYNC结果到client,这个消息最初由client发起,用来强制获取最新的更新 |
REVALIDATE | 用于延长SESSION有效时间 |
写请求
,就会把请求转发给leader,leader通过内部的Zab协议
进行原子广播,直到所有zk节点都成功写了数据并commit后,这次写请求算是完成,然后zk server就会给client发回响应。
写流程
写数据流
zk满足了CAP定理的分区容错性P和一致性C,牺牲了可用性A。zk的存储能力是有限的,当节点数据太大
/节点层次太深
/子节点太多
,都会影响到其稳定性。所以zk不是一个用来做高并发高性能的数据库,zk一般只用来存储配置信息。
zk的读性能随着节点数量的提升能不断增加,但是写性能会随着节点数量的增加而降低。所以节点的数量不宜太多,一般配置成3个或者5个,3个节点可以容忍挂掉1个节点,5个节点可以容忍挂掉2个节点。另外可以通过observer来提升zk的读性能。
所有的事务请求必须由一个全局唯一的Leader服务器来协调处理,集群其余的服务器称为learner服务器。Leader服务器负责将一个客户端请求
转化为事务提议(Proposal),并将该proposal分发给集群所有的follower服务器。之后Leader服务器需要等待所有的follower服务器的反馈,一旦超过了半数的follower服务器进行了正确反馈后,那么Leader服务器就会再次向所有的follower服务器分发commit消息,要求其将前一个proposal进行提交。
Zab协议包括两种基本的模式:崩溃恢复和消息广播。
恢复模式
并选举产生新的Leader服务器消息广播模式
Zab原子广播保证多个指令执行的顺序。
Leader选举
是保证分布式数据一致性的关键所在。当zk集群中的一台服务器出现以下两种情况之一时,需要进入Leader选举
(SID, ZXID)
用于标识一次投票信息。
假定zk由5台机器组成,SID分别为1、2、3、4、5,ZXID分别为9、9、9、8、8,并且此时SID为2的机器是Leader机器,某一时刻,1、2所在机器出现故障,因此集群开始进行Leader选举。在第一次投票时,每台机器都会将自己作为投票对象,于是SID为3、4、5的机器投票情况分别为(3, 9),(4, 8), (5, 8)投票
后,也会收到其他机器的投票,每台机器会根据一定规则
来处理收到的其他机器的投票,并以此来决定是否需要变更自己的投票,这个规则也是整个Leader选举算法的核心所在,
认可
当前收到的投票,并再次将该投票发送出去坚持
自己的投票,不做任何变更确定Leader。经过第二轮投票后,集群中的每台机器都会再次
接收到其他机器的投票,然后开始统计投票,如果一台机器收到了超过半数的相同投票,那么这个投票对应的SID机器即为Leader。
zk的Watcher机制,概括为三个过程:客户端注册Watcher成为订阅者、服务端处理Watcher以及客户端回调Watcher。 客户端在自己需要关注的ZNode节点上注册getData/exists/getChildren一个Watcher监听后,一旦这个ZNode节点发生变化,则在该节点上注册过Watcher监听的所有客户端会收到ZNode节点变化通知NodeDataChanged/NodeChildrenChanged等。在收到通知时,客户端通过回调Watcher做相应的处理,从而实现特定的功能。