第一章 Zookeeper理论基础

1.1 什么Zookeeper?

  开源的分布式应用程序协调服务器,为分布式系统提供一致性服务。通过Paxos算法和ZAB协议完成,主要功能包括:配置维护、域名服务、分布式同步、集群管理

1.2 一致性

1.2.1 顺序一致性

  同一个客户端发起的多个事务请求,最终会严格按照其发起顺序记录到zk中

1.2.2 原子性

  所有请求在ZK集群中的每个节点上是一致的,要么全部节点都是成功,要么全部都是失败

1.2.3 单一视图

  客户端连接的集群中任意一节点,读取的数据都是一致的

1.2.4 可靠性

  一旦事务被成功应用到zk,会一直保留下来,除非另一个事务将其修改

1.2.5 最终一致性

  一旦一个事务被成功应用,zk可以保证在较短时间内,客户端最终一定能从服务端读取到最新的数据,但不保证实时读取到

1.3 Paxos算法

  prepare阶段:提案者发送提案的编号为N给所有表决者,表决者用自己保存的最大接收编号maxN比较,只有N > maxN才同意,表决者缓存maxN = N,并发送自己历史最大接收提案 Proposal(myid,maxN,value)

  accept阶段:当半数表决者同意,提案者发送正真提案,Proposal(myid,N,value),表决者收到后,再次用maxN比较,只有N >= maxN,才同意,并更新Proposal(myid,N,value)。

  prepare和accept都必须要半数以上表决者同意,否则提案者只能重新进入prepare阶段

1.3.1 活锁问题

  

  (图引用:https://blog.csdn.net/wolf_love666/article/details/92832811) 

  解决办法,只允许一个进程提交提案,即对N的增长有唯一操作权限

1.4 ZAB协议  

  zookeeper 原子广播协议。当客户端连接到zk集群的一个节点后,如果客户端提交的读请求,节点直接响应。如果提交的是写请求,且当前节点不是Leader,会将请求转发给Leader,Leader以提案的方式广播该写操作,只有半数以上的节点同意写操作,写操作才会被提交,之后Leader会再次广播给所有订阅者,即Learner,通知它们同步数据。

1.4.1 三类角色

  • Leader:事务请求的唯一处理者,也可以处理读请求
  • Follower:处理客户端读请求,将事务请求转发给Leader,对Leader的提案有表决权,同时可以参加Leader的选举,有选举权和被选举权
  • Observer:不参与选举,没有选举权和被选举权。可以协助Follower处理读请求,用来提高集群读请求吞吐量,同时不会增加选举压力

  再分类:

  • Learner:需要从Leader中同步数据的节点,Follower+Observer
  • QuorumServer:能参与选举的节点,Leader+Follower

1.4.2 三个数据

  • zxid:Long型数字,高32位代表epoch,低32位表示xid
  • epoch:每个Leader选举结束会生成一个新的epoch,通知到集群中其他节点,包含Follower和Observer
  • xid:事务ID

1.4.3 三种模式

  • 恢复模式:Leader崩溃或集群启动过程中,系统进入恢复模式,包含Leader选举和初始化同步
  • 广播模式:初始化广播和更新广播
  • 同步模式:初始化同步和更新同步。初始化广播触发Learner进行初始化同步,将初始化广播中的事务同步到本地。类似更新同步由更新广播触发,将正常通信阶段的事务同步到本地。

1.4.4 四种状态

  集群中每个节点可能的状态

  • LOOKING:选举状态
  • FOLLOWING:Follower的正常工作状态
  • OBSERVING:Observer的正常工作状态
  • LEADING:Leader的正常工作状态

1.4.5 同步模式和广播模式

  1. 初始化广播

  选举完毕后只是准Leader,需要经过初始化同步后,才能变成真正的Leader。这期间会将Leader本身有而其他Learner没有的事务广播出去,并且探测一下活跃的Learner。

  1. 为每个Learner创建一个FIFO队列
  2. 将新Leader中未同步的事务封装成Proposal
  3. 将Proposal逐条发送给各个Learner,并紧接着附加一个COMMIT消息
  4. Learner收到消息,更新到本地,成功后返回ACK
  5. Leader收到ACK后,将对应Learner加入可用的Follower或者Observer列表

  2. 消息广播算法

  当初始化完毕后,进入正常工作模式,当非Leader收到事务请求,将转发给Leader

  1. Leader封装事务为Proposal,并生成一个全局唯一的zxid
  2. 从Follower列表获取所有Follower,将Proposal通过各自的FIFO队列发送给对方
  3. Follower收到后,对比自身存储的最大zxid。大于最大zxid,存储到本地事务日志,返回Leader ACK
  4. 当Leader收到过半ACK,向所有Follower队列发送COMMIT消息,向所有Observer队列发送Proposal
  5. Follower收到后,会将日志中的事务正式更新到本地。Observer收到后,直接应用事务到本地。两者处理完后都需要发送ACK

  3. Observer的数量问题

  一般与Follower数量相同,Observer需要从Leader同步数据,但Observer同步时间小于等于Follower的同步时间,一旦Follower同步完成,那么Observer同步也将结束,这就导致可能部分尚未完成同步,那么这些未同步完成的Observer将不能对外提供服务,造成浪费

1.4.6 恢复模式的三个原则

  1. Leader的主动让出原则

  当Leader收到Follower的心跳数量没有过半,此时Leader认为自己与集群的连接出现问题,会主动修改自己的状态为LOOKING,寻找新的Leader,防止出现脑裂。其他Server有过半主机发现Leader丢失,将会选举新的Leader

  2. 已经处理过的消息不能丢弃原则

  当Leader发送的COMMIT消息未完全被learner接收,Leader宕机,当新Leader选举后,需要根据这个来恢复执行

  3. 被丢弃的消息不能再现原则

  Leader在prepare阶段通过的事务,在发送COMMIT阶段之前宕机,再次上线后,需要丢弃这个事务

1.4.7 Leader选举

  1. myid:也称为ServerId,是zk集群中服务器的唯一标识

  2. 逻辑时钟:Logicalclock,选举完毕,变成epoch

  一、集群启动中的Leader选举

  只有所有节点都处在LOOKING状态才能进行选举。每个服务器启动后,状态为LOOKING,会给自己投票(myid,zxid),将投票发送给集群所有服务器。投票的比较规则:

  • 优先检查zxid,较大的优先作为Leader
  • 若相同,比较myid,较大的作为Leader

  每个服务器会选出优胜票更新投票,直到有半数服务器收到相同的投票信息,优胜的更新状态为LEADING,失败的更新为FOLLOWING

  若后续再有服务器启动,发现其余节点不是LOOKIGN,自动更新状态为FOLLOWING

  二、宕机后的Leader选举

  首先更新状态为LOOKING,然后发送投票,每个服务器依然投给自己(myid,zxid),注意此时zxid可不是启动时的0。后续步骤一致

1.5 高可用集群的容灾

1.5.1 服务器数量的奇数和偶数

  无论写操作投票还是Leader选举的投票都需要半数以上节点同意,所以当半数以上节点宕机,则投票永远无法通过。如5台服务器只允许2台宕机,而6台也只允许2台宕机,所以5台和6台的容灾能力是一样的,基于容灾考虑,建议部署5台服务器避免浪费,但基于吞吐量,6台服务器更好

1.5.2 容灾设计方案

  多机房部署设计,要充分考虑过半原则。比如三机房部署,每个机房中的主机数量要少于集群总数的一半,这样一个机房断网或断电,集群仍可以对外提供服务。双机房部署,需要个机房过半

1.6 ZK和CAP

  zk遵循的是CP原则,牺牲了可用性。

  1. 当Leader宕机后,zk集群在选举时,不提供读写服务。

  2. 当过半下线后,集群也无法提供服务。

1.7 ZK可能出现脑裂

  多机房部署,当出现网络连接,形成多个分区,可能出现脑裂,导致数据不一致。

  

人生就像蒲公英,看似自由,其实身不由己。
原文地址:https://www.cnblogs.com/walker993/p/14802358.html