Zookeeper学习

为什么需要zookeeper,zookeeper作用是什么?

Zookeeper主要用于分布式系统中,为了提供高可用的服务,作用主要包括两点:1)在主备节点之间选举主节点

2)在发生宕机重启等意外情况时,使某个值达成一致,保证不论发生以上任何异常,都不会破坏决议一致性。

  1. 在kafaka集群中,通过Zookeeper管理集群配置,选举leader,以及在consumer group发生变化时进行rebalance
  2. Hadoop,使用Zookeeper的事件处理确保整个集群只有一个NameNode,存储配置信息等.
    3)HBase,使用Zookeeper的事件处理确保整个集群只有一个HMaster,察觉HRegionServer联机和宕机,存储访问控制列表等.

Zookeeper原理

Zookeeper中的角色:

Leader:领导者,负责进行投票的发起和决议,更新系统状态

Learner:

Follower:追随者接收客户请求并向客户端返回结果,在选主过程中进行投票

Observer:观察者不参与投票,仅同步leader的状态。目的是为了扩展系统,提高读取速度。

Client:请求发起方

 

Zookeeper中节点在工作过程中有三种状态:

LOOKING:当前Server不知道leader是谁,正在搜寻

LEADING:当前Server即为选举出来的leader

FOLLOWING:leader已经选举出来,当前Server与之同步

Zookeeper与客户端

zookeeper原理解析

 

 

Zookeeper节点数据操作流程

zookeeper原理解析

整体流程如下:

1.在Client向Follwer发出一个写的请求

2.Follwer把请求发送给Leader

3.Leader接收到以后开始发起投票并通知Follwer进行投票

4.Follwer把投票结果发送给Leader

5.Leader将结果汇总后如果需要写入,则开始写入同时把写入操作通知给Leader,然后commit;

6.Follwer把请求结果返回给Client

 

Paxos算法

基于消息传递通信模型的分布式系统,不可避免的会发生以下错误:进程可能会 慢、被杀死或者重启,消息可能会延迟、丢失、重复,在基础 Paxos 场景中,先不考虑可能 出现消息篡改即拜占庭错误(Byzantine failure,即虽然有可能一个消息被传递了两次,但是 绝对不会出现错误的消息)的情况。Paxos 算法解决的问题是在一个可能发生上述异常的分 布式系统中如何就某个值达成一致,保证不论发生以上任何异常,都不会破坏决议一致性。

 

Paxos 算法使用一个希腊故事来描述,在 Paxos 中,存在三种角色,分别为

 

Proposer(提议者,用来发出提案 proposal)

Acceptor(接受者,可以接受或拒绝提案)

Learner(学习者,学习被选定的提案,当提案被超过半数的 Acceptor 接受后为被批准)

  下面更精确的定义 Paxos 要解决的问题:

1、决议(value)只有在被 proposer 提出后才能被批准

2、在一次 Paxos 算法的执行实例中,只批准(chose)一个 value

3、learner 只能获得被批准(chosen)的 value

 

ZooKeeper 的选举算法有两种:一种是基于 Basic Paxos(Google Chubby 采用)实现的,另外 一种是基于 Fast Paxos(ZooKeeper 采用)算法实现的。系统默认的选举算法为 Fast Paxos。 并且 ZooKeeper 在 3.4.0 版本后只保留了 FastLeaderElection 算法。

 

ZooKeeper 的核心是原子广播,这个机制保证了各个 Server 之间的同步。实现这个机制的协 议叫做 ZAB 协议(Zookeeper Atomic BrodCast)。 ZAB 协议有两种模式,它们分别是崩溃恢复模式(选主)和原子广播模式(同步)。

 

1、当服务启动或者在领导者崩溃后,ZAB 就进入了恢复模式,当领导者被选举出来,且大 多数 Server 完成了和 leader 的状态同步以后,恢复模式就结束了。状态同步保证了 leader 和 follower 之间具有相同的系统状态。

 

    2、当 ZooKeeper 集群选举出 leader 同步完状态退出恢复模式之后,便进入了原子广播模式。 所有的写请求都被转发给 leader,再由 leader 将更新 proposal 广播给 follower

 

   为了保证事务的顺序一致性,zookeeper 采用了递增的事务 id 号(zxid)来标识事务。所有 的提议(proposal)都在被提出的时候加上了 zxid。实现中 zxid 是一个 64 位的数字,它高 32 位是 epoch 用来标识 leader 关系是否改变,每次一个 leader 被选出来,它都会有一个新 的 epoch,标识当前属于那个 leader 的统治时期。低 32 位用于递增计数。 

ZooKeeper 的集群选主实例

  以一个简单的例子来说明整个选举的过程:假设有五台服务器组成的 zookeeper 集群,它们 的 serverid 从 1-5,同时它们都是最新启动的,也就是没有历史数据,在存放数据量这一点 上,都是一样的。假设这些服务器依序启动,来看看会发生什么

 

1、服务器 1 启动,此时只有它一台服务器启动了,它发出去的报没有任何响应,所以它的 选举状态一直是 LOOKING 状态

 

2、服务器 2 启动,它与最开始启动的服务器 1 进行通信,互相交换自己的选举结果,由于 两者都没有历史数据,所以 id 值较大的服务器 2 胜出,但是由于没有达到超过半数以上的服务器都同意选举它(这个例子中的半数以上是 3),所以服务器 1、2 还是继续保持 LOOKING 状态

 

    3、服务器 3 启动,根据前面的理论分析,服务器 3 成为服务器 1,2,3 中的老大,而与上面不 同的是,此时有三台服务器(超过半数)选举了它,所以它成为了这次选举的 leader

 

4、服务器 4 启动,根据前面的分析,理论上服务器 4 应该是服务器 1,2,3,4 中最大的,但是 由于前面已经有半数以上的服务器选举了服务器 3,所以它只能接收当小弟的命了

 

5、服务器 5 启动,同 4 一样,当小弟

 

ZooKeeper 的非全新集群选主

  那么,初始化的时候,是按照上述的说明进行选举的,但是当 zookeeper 运行了一段时间之 后,有机器 down 掉,重新选举时,选举过程就相对复杂了。

 

  需要加入数据 version、serverid 和逻辑时钟。

数据 version:数据新的 version 就大,数据每次更新都会更新 version

server id:就是我们配置的 myid 中的值,每个机器一个

 逻辑时钟:这个值从 0 开始递增,每次选举对应一个值,也就是说:如果在同一次选举中, 那么这个值应该是一致的;逻辑时钟值越大,说明这一次选举 leader 的进程更新,也就是 每次选举拥有一个 zxid,投票结果只取 zxid 最新的

  选举的标准就变成:

1、逻辑时钟小的选举结果被忽略,重新投票

2、统一逻辑时钟后,数据 version 大的胜出

3、数据 version 相同的情况下,server id 大的胜出

 根据这个规则选出 leader。

 

 

 

Raft算法

 

和paxos类似,区别如下两点:

raft 是基于对multi paxos 的两个限制形成的:

  • 发送的请求的是连续的, 也就是说raft 的append 操作必须是连续的. 而paxos 可以并发的. (其实这里并发只是append log 的并发提高, 应用的state machine 还是必须是有序的)
  • 选主是有限制的, 必须有最新, 最全的日志节点才可以当选. 而multi-paxos 是随意的 所以raft 可以看成是简化版本的multi paxos(这里multi-paxos 因为允许并发的写log, 因此不存在一个最新, 最全的日志节点, 因此只能这么做. 这样带来的麻烦就是选主以后, 需要将主里面没有的log 给补全, 并执行commit 过程)

思考个问题:

Zookeeper为什么需要2n+1个server,发生了宕机,什么情况下会不能使用?

只有一个不稳定,宕机系统就瘫了,2或偶数个的话,会出现一半选举这个另一半选举那个,此时无法决断

2n+1台server,只要有n+1台就可以使用。也就是你说的少于一半集群就无效了

相关文章: