ZooKeeper集群解析
ZooKeeper集群解析
作者:IT王小二
这篇文章中来介绍一下 ZooKeeper 相关的集群角色,还有 ZAB协议,集群的安装在ZooKeeper入门
中有介绍。
一、ZooKeeper集群中的角色
- Leader 集群工作机制中的核心事务请求的唯一调度和处理者,保证集群事务处理的顺序集群内部个服务器的调度者(管理 follower,数据同步),为客户端提供读和写的服务,负责投票的发起和决议,更新系统状态。
- Follower 集群工作机制中的跟随者处理非事务请求,为客户端提供读服务,如果是写服务则转发给Leader,参与事务请求 proposal 投票参与 leader 选举投票。
- Observer 观察者3.30 以上版本提供,和 follower 功能相同,但不参与任何形式投票处理非事务请求,转发事务请求给 Leader 提高集群非事务处理能力,如果版本高于3.30需要配置使用方式:
server.0=192.168.182.130:2888:3888:Observer
。
二、ZooKeeper集群一致性协议ZAB
ZAB协议的实现借鉴于 Paxos,是为了解决分布式系统的数据一致性问题。
1. 总览
zookeeper 就是根据 zab 协议建立了主备模型完成集群的数据同步(保证数据的一致性),前面介绍了集群的各种角色,这说所说的主备架构模型指的是,在 zookeeper 集群中,只有一台 leader(主节点)负责处理外部客户端的事务请求(写操作),leader 节点负责将客户端的写操作数据同步到所有的 follower 节点中,大概流程如下:
- zab 协议核心是在整个 zookeeper 集群中只有一个节点既 leader 将所有客户端的写操作转化为事务(提议 proposal),leader 节点再数据写完之后,将向所有的 follower 节点发送数据广播请求(数据复制)。
- 等所有的 follower 节点的反馈。
- 在 zab 协议中,只要超过半数 follower 节点反馈 ok,leader 节点会向所有 follower 服务器发送 commit 消息,既将 leader 节点上的数据同步到 follower 节点之上。
2. 崩溃恢复
什么时候会发生崩溃恢复?
- 当服务器启动时
- 当leader 服务器出现网络中断,崩溃或者重启的情况
- 当集群中已经不存在过半的服务器与Leader服务器保持正常通信
崩溃恢复的过程
- 每个 Server 会发出一个投票,第一次都是投自己。投票信息:(myid,ZXID)
- 收集来自各个服务器的投票
- 处理投票并重新投票,处理逻辑:优先比较 ZXID,然后比较 myid
- 统计投票,只要超过半数的机器接收到同样的投票信息,就可以确定 leader
- 改变服务器状态
为什么要有限比较ZXID呢?
因为ZXID为事务id,值越大,证明它的数据最新。
在这个选举过程中每个 Server 有三种状态:
- LOOKING:当前Server不知道leader是谁,正在搜寻
- LEADING:当前Server即为选举出来的leader
- FOLLOWING:leader已经选举出来,当前Server与之同步
两种特殊情况
- 已经被处理的事务请求(proposal)不能丢(commit的)。
- 没被处理的事务请求(proposal)不能再次出现。
情况一的出现场景:
当 leader 收到合法数量 follower 的 ACK 后,就向各个 follower 广播 commit 命令,同时也会在本地执行 commit 并向连接的客户端返回 成功,但是如果在各个 follower 在收到 commit 命令前 leader 就挂了,导致剩下的服务器并没有执行都这条消息。
那么这种情况要怎么处理呢?
- 选举 ZXID 最大的节点作为新的 leader:由于所有提案被 commit 之前必须有合法数量的 follower ACK,即必须有合法数量的服务器的事务日志上有该 proposal,因此,ZXID 最大也就是数据最新的节点保存了所有被 commit 消息的 proposal 状态。
- 新的 leader 将自己事务日志中 proposal 但未 COMMIT 的消息处理。
- 新的 leader 与 follower 建立先进先出的队列, 先将自身有而 follower 没有的 proposal 发送给 follower,再将这些 proposal 的 COMMIT 命令发送给 follower,以保证所有的 follower 都保存了所有的 proposal、所有的 follower 都处理了所有的消息,通过以上策略,能保证已经被处理的消息不会丢。
情况二的出现场景
当 leader 接收到消息请求生成 proposal 后就挂了,其他 follower 并没有收到此 proposal,因此经过恢复模式重新选了 leader 后,这条消息是被跳过的,此时,之前挂了的 leader 重新启动并注册成了 follower,他保留了被跳过消息的 proposal 状态,与整个系统的状态是不一致的,所以需要将其删除。
3. 消息广播
在 zookeeper 集群中数据副本的传递策略就是采用的广播模式,Zab 协议中的 leader 等待 follower 的 ack 反馈,只要半数以上的 follower 成功反馈就好,不需要收到全部的 follower 反馈。
具体步骤如下:
- 客户端发起一个写操作请求
- Leader 服务器将客户端的 request 请求转化为事物 proposql 提案,同时为每个 proposal 分配一个全局唯一的 ID,即 ZXID
- leader 服务器与每个 follower 之间都有一个队列,leader 将消息发送到该队列
- follower 机器从队列中取出消息处理完(写入本地事物日志中)毕后,向 leader 服务器发送 ACK 确认
- leader 服务器收到半数以上的 follower 的 ACK 后,即认为可以发送 commit
- leader 向所有的 follower 服务器发送 commit 消息