Zookeeper 定义与工作原理
面向分布式应用的分布式协调服务
一致性协调
CAP
- Consistency:一致性(每次读操作都能保证返回的是最新数据)
- Availability:可用性(任何一个没有发生故障的节点,会在合理的时间内返回一个正常的结果)
- Partition tolerance:分区容错(当节点间出现网络分区,照样可以提供满足一致性和可用性的服务)
备注:因为P是必须的,因此往往选择就在CP或者AP中
2PC (Two-Phase Commit)
二阶段提交算法
- 阶段一:提交事务请求
- 阶段二:执行事务提交
示意
协调者 参与者
QUERY TO COMMIT
-------------------------------->
VOTE YES/NO prepare*/abort*
<-------------------------------
commit*/abort* COMMIT/ROLLBACK
-------------------------------->
ACKNOWLEDGMENT commit*/abort*
<--------------------------------
end
缺点:2PC的缺点也很致命:同步阻塞,单点问题,数据不一致,太过保守
3PC (Three-Phase Commit)
三阶段提交算法
- 阶段一:CanCommit
- 阶段二:PreCommit
- 阶段三:doCommit
协调者 参与者
CanCommit
-------------------------------->
VOTE YES/NO uncertain
<-------------------------------
Commit authorized PreCommit
-------------------------------->
ACK prepared to commit
<--------------------------------
Finaliazing commit DoCommit
-------------------------------->
haveCommitted commited
<--------------------------------
end
引入超时机制。同时在协调者和参与者中都引入超时机制。
在第一阶段和第二阶段中插入一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。
Paxos 算法
Basic Paxos
- 提议者(Proposer):代表的是接入和协调功能,收到客户端请求后,发起二阶段提交,进行共识协商;
- 接受者(Acceptor):代表投票协商和存储数据,对提议的值进行投票,并接受达成共识的值,存储保存;
- 学习者(Learner):代表存储数据,不参与共识协商,只接受达成共识的值,存储保存。
过程
- 阶段一:
- (a) Proposer选择一个提案编号N,然后向半数以上的Acceptor发送编号为N的Prepare请求。
- (b) 如果一个Acceptor收到一个编号为N的Prepare请求,且N大于该Acceptor已经响应过的所有Prepare请求的编号,那么它就会将它已经接受过的编号最大的提案(如果有的话)作为响应反馈给Proposer,同时该Acceptor承诺不再接受任何编号小于N的提案。
- 阶段二:
- (a) 如果Proposer收到半数以上Acceptor对其发出的编号为N的Prepare请求的响应,那么它就会发送一个针对[N,V]提案的Accept请求给半数以上的Acceptor。注意:V就是收到的响应中编号最大的提案的value,如果响应中不包含任何提案,那么V就由Proposer自己决定。
- (b) 如果Acceptor收到一个针对编号为N的提案的Accept请求,只要该Acceptor没有对编号大于N的Prepare请求做出过响应,它就接受该提案。
实际应用
- database replication, log replication等, 如bdb的数据复制就是使用paxos兼容的算法。Paxos最大的用途就是保持多个节点数据的一致性。
- naming service, 通过Paxos算法来管理所有的naming服务,则可保证high available分配可用的service给client。象ZooKeeper还提供watch功能,即watch的对象发生了改变会自动发notification, 这样所有的client就可以使用一致的,高可用的接口。
- config配置管理
Zookeeper 集群模式
- 同步时间所有节点的时间,并关闭防火墙
- 至少需要3台主机进行搭建
- 配置集群server
Zookeeper工作原理
ZAB(ZooKeeper Atomic Broadcast) 原子消息广播协议
保证主从节点的状态同步
在Paxos算法基础上的扩展;支持崩溃恢复;ZK使用单一主进程Leader处理所有事务请求;
Leader选举
服务器启动时期的 Leader 选举
- 每个Server发出一个投票投给自己。由于是初始情况,Server1和Server2都会将自己作为Leader服务器来进行投票,每次投票会包含所推举的服务器的myid和ZXID,使用(myid, ZXID)来表示,此时Server1的投票为(1, 0),Server2的投票为(2, 0),然后各自将这个投票发给集群中其他机器。
- 接受来自各个服务器的投票。集群的每个服务器收到投票后,首先判断该投票的有效性,如检查是否是本轮投票、是否来自LOOKING状态的服务器。
- 处理投票。针对每一个投票,服务器都需要将别人的投票和自己的投票进行PK,优先检查ZXID,在检查myid。比较大的服务器优先作为Leader。
- 统计投票。每次投票后,服务器都会统计投票信息,判断是否已经有过半机器接受到相同的投票信息,对于Server1、Server2而言,都统计出集群中已经有两台机器接受了(2, 0)的投票信息,此时便认为已经选出了Leader。
- 改变服务器状态。一旦确定了Leader,每个服务器就会更新自己的状态,如果是Follower,那么就变更为FOLLOWING,如果是Leader,就变更为LEADING。
服务器运行时期的 Leader 选举
- 变更状态。Leader挂后,余下的非Observer服务器都会将自己的服务器状态变更为LOOKING,然后开始进入Leader选举流程。
- 每个Server会发出一个投票。在这个过程中,需要生成投票信息(myid,ZXID)每个服务器上的ZXID可能不同。
- 接收来自各个服务器的投票。与启动时过程相同。
- 处理投票。与启动时过程相同,此时,Server1将会成为Leader。
- 统计投票。与启动时过程相同。
- 改变服务器的状态。与启动时过程相同。
应用
- 统一命名服务:在分布式环境下,经常需要对应用/服务进行统一命名,便于识别;
- 统一配置管理:配置文件同步、管理;
- 统一集群管理:可以实现实时监控节点状态变化,服务将节点信息写入;
- 服务器动态上下线:
- 软负载均衡:记录每台服务器的访问数;
节点类型
- 持久化目录节点:客户端与 Zookeeper 断开连接后,该节点依旧存在。
- 持久化顺序编号目录节点:客户端与 Zookeeper 断开连接后,该节点依旧存在,只是 Zookeeper 给该节点名称进行顺序编号
- 临时目录节点:客户端与 Zookeeper 断开连接后,该节点被删除
- 临时顺序编号目录节点:客户端与 Zookeeper 断开连接后,该节点被删除,只是 Zookeeper 给该节点名称进行顺序编号。
- 持久化目录节点:用于长连接;如用zk来管理数据库创建持久化节点可以避免频繁与数据库的交互,而带来的资源消耗;持久化节点也有弊端:不能及时的获取最新的资源;
- 持久化顺序编号目录节点:使用场景少,用于复杂业务中有序的获取资源;
- 临时目录节点:常见的dubbo架构中service服务的注册,分布式锁(原理后面文章会讲解【–创建相同节点时返回false】)
- 临时顺序编号目录节点:用于分布式锁实现复杂业务有序处理;
Stat结构体
- czxid: 创建节点的事务 zxid(每次修改 ZooKeeper 状态都会收到一个 zxid 形式的时间戳,也就是 ZooKeepe r事务 ID。事务 ID 是 ZooKeeper 中所有修改总的次序。每个修改都有唯一的 zxid,若 zxid1 小于 zxid2,那么 zxid1 在 zxid2 之前发生。)
- ctime: znode 被创建的毫秒数(从 1970 年开始)
- mzxid: znode 最后更新的事务 zxid
- mtime: znode 最后修改的毫秒数(从 1970 年开始)
- pZxid: znode 最后更新的子节点 zxid
- cversion : znode 子节点变化号,znode 子节点修改次数
- dataversion: znode 数据变化号
- aclVersion: znode 访问控制列表的变化号
- ephemeralOwner: 如果是临时节点,这个是 znode 拥有者的 session id。如果不是临时节点则是 0。
- dataLength: znode 的数据长度
- numChildren: znode 子节点数量
监听器
- 监听节点数据的变化
- 监听子节点增减的变化