基于zookeeper的分布式配置中心(一) (2)

  zookeeper集群采用主从(leader-follower)模式保证服务高可用。leader节点可读可写,follower节点只读,这种模式就需要保证leader节点和follower节点的数据一致性。对于客户端发送的写请求,全部由 Leader 接收,Leader 将请求封装成一个事务 Proposal,将其发送给所有 Follwer ,然后,根据所有 Follwer 的反馈,如果超过半数成功响应,则执行 commit 操作(先提交自己,再发送 commit 给所有 Follwer)。

  注:上述中有一个概念:两阶段提交过程(分布式系统中数据一致性经常会涉及到的方案)。follower节点是可以处理写请求的,会转发给leader节点。leader节点通过消息广播(二阶段提交)同步写操作到follower节点,保证数据一致性。

  zookeeper中每个事务都对应一个ZXID(全局的、唯一的、顺序的)。ZXID 是一个 64 位的数字,其中低 32 位可以看作是一个简单的递增的计数器,针对客户端的每一个事务请求,Leader 都会产生一个新的事务 Proposal 并对该计数器进行 + 1 操作。而高 32 位则代表了 Leader 服务器上取出本地日志中最大事务 Proposal 的 ZXID,并从该 ZXID 中解析出对应的 epoch 值,然后再对这个值加一。

崩溃恢复

  即如果在消息广播的过程中,leader死掉了,如何保证数据的一致性问题。

  假设两种异常情况:
  1、一个事务在 Leader 上提交了,并且过半的 Folower 都响应 Ack 了,但是 Leader 在 Commit 消息发出之前挂了。
  2、假设一个事务在 Leader 提出之后,Leader 挂了。

  考虑到上述两种异常情况,Zab 协议崩溃恢复要求满足以下两个要求:
  1)确保已经被 Leader 提交的 Proposal 必须最终被所有的 Follower 服务器提交。
  2)确保丢弃已经被 Leader 提出的但是没有被提交的 Proposal。

  崩溃恢复主要包含:leader选举 和 数据恢复。

  leader选举:

  1、要求 可用节点数量 > 总节点数量/2  。注意 是 > , 不是 ≥。

     2、新选举出来的 Leader 不能包含未提交的 Proposal(新选举的 Leader 必须都是已经提交了 Proposal 的 Follower 服务器节点) 、新选举的 Leader 节点中含有最大的 zxid(可以避免 Leader 服务器检查 Proposal 的提交和丢弃工作。如果zxid相同,选择server_id【zoo.cfg中的myid】最大的。)

  数据恢复

  1、上面讲过了ZXID的高 32 位代表了每代 Leader 的唯一性,低 32 代表了每代 Leader 中事务的唯一性。同时,也能让 Follwer 通过高 32 位识别不同的 Leader。简化了数据恢复流程。

  2、基于这样的策略:当 Follower 链接上 Leader 之后,Leader 服务器会根据自己服务器上最后被提交的 ZXID 和 Follower 上的 ZXID 进行比对,比对结果要么回滚,要么和 Leader 同步。

zookeeper集群脑裂

  集群的脑裂通常是发生在节点之间通信不可达的情况下,集群会分裂成不同的小集群,小集群各自选出自己的master节点,导致原有的集群出现多个master节点的情况。

zookeeper集群节点数(奇数or偶数?)

  只要我们清楚集群leader选举的要求(可用节点数量 > 总节点数量/2  。注意 是 > , 不是 ≥),我相信很容易明白奇数节点集群相比偶数节点的集群有更大的优势。

  1、发生脑裂(分成2个小集群)的情况下,奇数节点的集群总会有一个小集群满足可用节点数量 > 总节点数量/2,所以zookeeper集群总能选取出leader。

  2、在容错能力相同的情况下,奇数集群更节省资源。还是要清楚leader选举的要求哈,举个列子:3个节点的集群,如果集群可以正常工作(即leader选举成功),至少需要2个节点是正常的;4个节点的集群,如果集群可以正常工作(即leader选举成功),至少需要3个节点是正常的。那么3个节点的集群和4个节点的集群都有一个节点宕机的容错能力。很明显,在容错能力相同的情况下,奇数节点的集群更节省资源。

 zookeeper和eureka对比

  在分布式系统领域有个著名的 CAP定理(C- 数据一致性;A-服务可用性;P-服务对网络分区故障的容错性,这三个特性在任何分布式系统中不能同时满足,最多同时满足两个)。

  zookeeper基于CP,即任何时刻对ZooKeeper的访问请求能得到一致的数据结果,同时系统对网络分割具备容错性;但是它不能保证每次服务请求的可用性(注:也就 是在极端环境下,zookeeper可能会丢弃一些请求,消费者程序需要重新请求才能获得结果)。至于zookeeper为啥不能保证服务的高可用,大家可以想一下发生脑裂后无法选取leader、选取leader过程中丢弃某些请求。当网络出现故障时,剩余zk集群server会发起投票选举新的leader,但是此过程会持续30~120s,此过程对于高并发来说十分漫长,会导致整个注册服务的瘫痪,这是不可容忍的。 

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpgwjx.html