Zookeeper解析

zk的角色

1.领导者(Leader):进行投票的发起和决议,更新系统状态

2.学习者(Learner)

  • 跟随者(Follower):接受客户端请求并向客户端返回结果,在选主过程中参与投票
  • 观察者(Observer):接收客户端的连接,将写请求转发给leader节点。但Observer不参加投票,只同步leader状态。Observer的目的是为了扩展系统,提高读取速度

3.客户端(Client):请求发起方

session

zookeeper会为每个client分配一个session,类似于web服务器一样。针对session可以有保存一些关联数据

  • Global session 全局session,在每个server上都存在
  • local session 只在当前请求的server上存在,但只能进行读操作,要是要进行写操作,就得升级为全局session
zk的结构图
Zookeeper解析_第1张图片
zookeeper集群上每个server数据一致,leader在集群启动时选举

  • 客户端写数据
请求发给某server,再由server转发给leader,leader给每个server发送投票消息,每个server把投票结果传给leader,要是有半数server同意此请求,leader就会commit到每个服务器执行写操作
投票是采用Quorum机制
1.请求发给follower
Zookeeper解析_第2张图片
2.请求发给Observer
Zookeeper解析_第3张图片
一个follower挂了,修复好之后会和leader通过一致性协议修复follower数据,达到每个server上数据最终一致
Watcher的特性:只通知改变事一次性、触发后失效、session内有效

Zk的分布式锁

Zookeeper解析_第4张图片
zk的应用
  • 分布式配置中心
  • 负载均衡                       将所有broker和对应的分区信息全部注册到ZK指定节点上,生产者在通过ZK获取分区列表之后,会按照brokerId和partition的顺序排列组织成一个有序的分区列表,然后轮询
  • 命名服务 rpc的服务发布,rpc的服务订阅
  • 分布式通知 watcher注册与异步通知机制
  • 集群管理 客户端在节点 x 上注册一个Watcher,那么如果 x?的子节点变化了,会通知该客户端
  • Master选举 利用ZooKeeper的强一致性,能够保证在分布式高并发情况下节点创建的全局唯一性,可以创建多个子节点,但是序号最小的才是master
  • 分布式锁 ZooKeeper为我们保证了数据的强一致性


Leader选举

  Leader选举是保证分布式数据一致性的关键所在。当Zookeeper集群中的一台服务器出现以下两种情况之一时,需要进入Leader选举。

  (1) 服务器初始化启动。

  (2) 服务器运行期间无法和Leader保持连接。

 

  • 每个server发出一个投票,然后将投票发给集群的其他机器
  • 集群每台服务器接收来自各个服务器的投票,然后处理投票:优先检查zxid,zxid大的服务器优先作为leader,如果zxidx相同,那就比较myid
  • 统计投票,判断是否过半机器接收到相同的投票信息
  • 改变服务器状态,如果是Follower,那么就变更为FOLLOWING,如果是Leader,就变更为LEADING。

 

服务器状态

  服务器具有四种状态,分别是LOOKING、FOLLOWING、LEADING、OBSERVING。

 

  • LOOKING:寻找Leader状态。当服务器处于该状态时,它会认为当前集群中没有Leader,因此需要进入Leader选举状态。
  • FOLLOWING:跟随者状态。表明当前服务器角色是Follower。
  • LEADING:领导者状态。表明当前服务器角色是Leader。
  • OBSERVING:观察者状态。表明当前服务器角色是Observer。

 

每台服务器在启动的过程中,会启动一个QuorumPeerManager,负责各台服务器之间的底层Leader选举过程中的网络通信。

FastLeaderElection算法

1. 自增选举轮次。Zookeeper规定所有有效的投票都必须在同一轮次中,在开始新一轮投票时,会首先对logicalclock进行自增操作。

2. 初始化选票。在开始进行新一轮投票之前,每个服务器都会初始化自身的选票,并且在初始化阶段,每台服务器都会将自己推举为Leader。

3. 发送初始化选票。完成选票的初始化后,服务器就会发起第一次投票。Zookeeper会将刚刚初始化好的选票放入sendqueue中,由发送器WorkerSender负责发送出去。

4. 接收外部投票。每台服务器会不断地从recvqueue队列中获取外部选票。如果服务器发现无法获取到任何外部投票,那么就会立即确认自己是否和集群中其他服务器保持着有效的连接,如果没有连接,则马上建立连接,如果已经建立了连接,则再次发送自己当前的内部投票。

 5. 判断选举轮次。在发送完初始化选票之后,接着开始处理外部投票。在处理外部投票时,会根据选举轮次来进行不同的处理。

· 外部投票的选举轮次大于内部投票。若服务器自身的选举轮次落后于该外部投票对应服务器的选举轮次,那么就会立即更新自己的选举轮次(logicalclock),并且清空所有已经收到的投票,然后使用初始化的投票来进行PK以确定是否变更内部投票。最终再将内部投票发送出去。

· 外部投票的选举轮次小于内部投票。若服务器接收的外选票的选举轮次落后于自身的选举轮次,那么Zookeeper就会直接忽略该外部投票,不做任何处理,并返回步骤4。

· 外部投票的选举轮次等于内部投票。此时可以开始进行选票PK。

6. 选票PK。在进行选票PK时,符合任意一个条件就需要变更投票。

    · 若外部投票中推举的Leader服务器的选举轮次大于内部投票,那么需要变更投票。

    · 若选举轮次一致,那么就对比两者的ZXID,若外部投票的ZXID大,那么需要变更投票。

    · 若两者的ZXID一致,那么就对比两者的SID,若外部投票的SID大,那么就需要变更投票。

7. 变更投票。经过PK后,若确定了外部投票优于内部投票,那么就变更投票,即使用外部投票的选票信息来覆盖内部投票,变更完成后,再次将这个变更后的内部投票发送出去。

8. 选票归档。无论是否变更了投票,都会将刚刚收到的那份外部投票放入选票集合recvset中进行归档。recvset用于记录当前服务器在本轮次的Leader选举中收到的所有外部投票(按照服务队的SID区别,如{(1, vote1), (2, vote2)...})。

9. 统计投票。完成选票归档后,就可以开始统计投票,统计投票是为了统计集群中是否已经有过半的服务器认可了当前的内部投票,如果确定已经有过半服务器认可了该投票,则终止投票。否则返回步骤4。

10. 更新服务器状态。若已经确定可以终止投票,那么就开始更新服务器状态,服务器首选判断当前被过半服务器认可的投票所对应的Leader服务器是否是自己,若是自己,则将自己的服务器状态更新为LEADING,若不是,则根据具体情况来确定自己是FOLLOWING或是OBSERVING。

  以上10个步骤就是FastLeaderElection的核心,其中步骤4-9会经过几轮循环,直到有Leader选举产生。


ZAB协议

同一时刻存在一个Leader节点,其他节点称为“Follower”,如果是更新请求,如果客户端连接到Leader节点,则由Leader节点执行其请求;如果连接到Follower节点,则需转发请求到Leader节点执行。但对读请求,Client可以直接从Follower上读取数据,如果需要读到最新数据,则需要从Leader节点进行,Zookeeper设计的读写比例是2:1。
ZAB协议中节点之间通信主要发生在Leader和Follower之间。他们之间主要的命令分为控制类和数据传输类。
Follower节点启动后,会主动连接Leader,而Leader会监听Follower的建立连接的请求。并为每个Follower的tcp连接创建一个LearnerHandler对象,主要作用是:
  • 接收Follower发来的请求,可能包括以下请求:Follower转发的客户端的更新请求(命令类型:Leader.REQUEST),Follower对Leader的Proposal命令的回复消息ACK,Follower给Leader发送的PING(Follower会给Leader发送PING消息?);
  • 给Follower发送心跳消息。
Leader抽象了集群当前的主节点,此类节点负责:
  • 处理所有客户端的更新请求,并将这些请求使用ZAB协议以日志同步方式广播至所有的Follower;
  • 通过心跳信息维护集群状态,在必要时会结束自己的Leader状态,触发新的选举
Follower抽象了集群的从节点,从节点负责:
  • 接受Leader命令,同步Leader节点日志,并将其应用到自身的状态机
  • 维护与Leader的心跳,并在Leader节点异常时会发起一次选举
QuorumPeer负责维护节点的选主状态信息,无论是Leader还是Follower,都需要记录这些信息。比如,当前节点的状态,当前节点选择了谁作为主,等等等等。

Paxos算法

Paxos算法是基于消息传递且具有高度容错特性的一致性算法,是目前公认的解决分布式一致性问题最有效的算法之一。

在Paxos算法中,有三种角色:

  • Proposer
  • Acceptor
  • Learners

在具体的实现中,一个进程可能同时充当多种角色。比如一个进程可能既是Proposer又是Acceptor又是Learner

还有一个很重要的概念叫提案(Proposal)。最终要达成一致的value就在提案里。

Proposer可以提出(propose)提案;Acceptor可以接受(accept)提案;如果某个提案被选定(chosen),那么该提案里的value就被选定了。

算法(决议的提出与批准)主要分为两个阶段:
  • 1. prepare阶段:
(1). 当Porposer希望提出方案V1,首先发出prepare请求至大多数Acceptor。Prepare请求内容为序列号;
(2). 当Acceptor接收到prepare请求时,检查自身上次回复过的prepare请求
a). 如果SN2>SN1,则忽略此请求,直接结束本次批准过程;
b). 否则检查上次批准的accept请求,并且回复;如果之前没有进行过批准,则简单回复;
  • 2. accept批准阶段:
(1a). 经过一段时间,收到一些Acceptor回复,回复可分为以下几种:
a). 回复数量满足多数派,并且所有的回复都是,则Porposer发出accept请求,请求内容为议案;
b). 回复数量满足多数派,但有的回复为:,……则Porposer找到所有回复中超过半数的那个,假设为,则发出accept请求,请求内容为议案;
c). 回复数量不满足多数派,Proposer尝试增加序列号为SN1+,转1继续执行;
(1b). 经过一段时间,收到一些Acceptor回复,回复可分为以下几种:
a). 回复数量满足多数派,则确认V1被接受;
b). 回复数量不满足多数派,V1未被接受,Proposer增加序列号为SN1+,转1继续执行;
(2). 在不违背自己向其他proposer的承诺的前提下,acceptor收到accept 请求后即接受并回复这个请求。

你可能感兴趣的:(网络通信,zookeeper,分布式)