Zookeeper学习笔记

简介

ZooKeeper 由雅虎研究院开发,后来捐赠给了 Apache。ZooKeeper 是一个开源的分布式应用程序协调服务器,其为分布式系统提供一致性服务。其一致性是通过基于 Paxos 算法的 ZAB 协议完成的。

其主要功能包括:

  • 配置维护

  • 域名服务

  • 分布式同步

  • 集群管理等

ZOOKEEPER理论基础

一、一致性

  • 顺序一致性

  • 原子性

  • 单一视图

  • 最终一致性

二、Paxos算法

前提:不存在拜占庭将军问题,也就是说信道是通畅的。

算法三种角色

在 Paxos 算法中有三种角色,分别具有三种不同的行为。但很多时候,一个进程可能同 时充当着多种角色。

  • Proposer:提案者,提议者,proposal的提议者

  • Acceptor:表决者

  • Learners:学习者

算法的两个阶段

  • prepare阶段

  • accept阶段

通俗来讲,prepare阶段是提案者向系统中的其他表决者发送一个提案,其目的是通过一个全局唯一且自增长的N值来确定在表决者那里这个提案是否是最新的,如果不是最新的,表决者是不会接收这个提案的,这种情况下,提案者可以选择重新提案或者放弃提案。

当提案者发现超过半数的表决者都已经接收了这个提案,将进入accept阶段。提案者会给每个表决者发送他的提案,这个阶段依然还要用与prepare阶段相同的策略来确定表决者那里这个提案还是不是最新的,不是最新的话,表决者将拒绝这个提案。若最终提案者发现超过半数的的表决者通过了这个提案,提案者会向外发送两类信息:

  • 向曾 accept 其提案的表决者发送“可执行数据同步信号”,即让它们执行其曾接收到的提案;

  • 向未曾向其发送 accept 反馈的表决者发送“提案 + 可执行数据同步信号”,即让

    它们接受到该提案后马上执行。

可以看到,paxos算法通过这种策略,来保证所有角色的一致性。

这里有一个问题:

在一个提案者提交提案的时候,其他提案者也是表决者从而参与表决吗?

活锁问题

死锁

死锁很好理解

截屏2020-03-17下午9.34.03.png

活锁

截屏2020-03-17下午9.37.20.png

Fast Paxos 算法只允许一个进程提交提案,即其具有对 N 的唯一操作权。该方式解决了 “活锁”问题。

三、ZAB协议

简介

因为为了解决活锁问题,只允许一个进程提交提案,能够提交提案的进程就是leader。leader如果挂了,怎么办呢?ZAB协议就是来解决这种问题的,他是一个转为Zookeeper设计的一种支持崩溃恢复(leader选举)的原子广播协议。

ZAB 协议是 Fast Paxos 算法的一种工业实现算法。但两者的设计目标不太一样。ZAB 协 议主要用于构建一个高可用的分布式数据主从系统(注意:是主从系统,而不是主备,主从意味着系统当中所有的服务器都向外提供服务),例如,Leader 挂了,马上就可以选举出 一个新的 Leader。而 Paxos 算法则是用于构建一个分布式一致性状态机系统,确保系统中各 个节点的状态都是一致的。

三个角色

  • leader:处理写请求,具有提案权。

  • follower:处理读请求以及写请求转发,具有选举权,被选举权,表决权。

  • observer:处理读请求(为了提升系统的吞吐量的扩展服务器),没有任何权利。

系统正常运行时可以把这三个角色名称抽象一下:

  • learner:observer和follower的统称,从leader处同步数据。

  • quorumServer:具有表决权的服务器。

三个数据

  • zxid:64位的数据(Long类型),高32位存储epoch,低32位存储xid。

  • epoch:每个新leader的时代号,存储在集群当中的所有角色当中。

  • xid:事务请求的流水号,只增不减。

  • 逻辑时钟:与epoch息息相关的一个数据,在leader选举部分会说。

三种模式

  • 恢复模式:leader崩溃的时候,重新启动会进入恢复模式,分为两个阶段,选举阶段和初始化阶段。

  • 广播模式:leader向外广播epoch,以及事务操作。

  • 同步模式:learner同步leader的事务操作。

四种状态

  • LOOKING:选举状态

  • FOLLOWING:Follower正常工作状态

  • OBSERVING:Observer正常工作状态

  • LEADING:Leader正常工作状态

在Paxos算法中的prepare和accept阶段中,通过比较N值,来确保每个表决者所接收的提案是最新的,然而在commit的时候却没有再次比较N值,这是一种机会主义,这同样会导致有角色保存了不是最新的提案。

为了解决这种问题,如果表决者在accept阶段N值的比较已经确定了其所接收到的提案仍然是最新的提案,那么这个表决者将被赋予一个状态,这种状态下他将不再去接收其它提案,以保证commit到来时,他所保存的提案是最新的。

这里有个问题:

一个事务请求对应的是一个提案吗?

如果是的话,那么两个事务请求来了,第一个事务请求被当做提案提交,第二个事务请求也被当做提案提交了,此时他们都处于prepare阶段,那么accept阶段的时候拿到第一个事务请求就不进行处理了吗?

我的猜想是,ZAB协议通过四种状态,控制了两个提案同时处于prepare阶段的可能性,从而保证每个请求都能够被正常通过并且commit。

答:后边也可以看到,在更新广播算法中,leader维护了一个请求队列来保证顺序,也就是说zk不允许leader一个事务请求还没有同步完成的时候,就去同步下一个事务请求。

可以看出来,ZAB协议对原始的Paxos算法做了非常多的工业上的实际处理。

初始化广播与更新广播算法

1. 初始化广播算法

leader被选举出来之后,他还只是一个准leader,需要经过初始化广播阶段才能算是真正的leader。初始化广播,就是把leader当中有的而其他learner没有的事务请求同步给其他learner

这里就涉及到一个问题:

leader是如何知道哪些事务请求是自己有而其他learner没有的呢?

初始化广播算法图解

截屏2020-03-20下午5.52.56.png

问题:

这里leader为每一个learner都创建一个队列,这个没明白什么意思,一个队列不行吗?一个队列就能够保证顺序了啊。难道是因为每个learner中的所保存的事务请求不同,leader为了针对每个learner的这种差异性去保存不同的事务请求,才设计了多个队列,恩,极有可能是这个原因。

2. 更新广播算法

当learner收到事务请求要把这个请求转发给leader去处理,然后算过更新广播算法把这个事务请求更新到每一个learner当中。算法图解如下:

截屏2020-03-20下午6.10.38.png

这里有两个问题

  1. fast paxos算法,是只有一个角色可以发请求,表决时,发送到follwer处的请求的zxid一定是比follwer的zxid大的。为什么还要进行第三步的比较?follower直接接受提案进行同步就好了啊。
答:ABA问题。
  1. 第8步,返回的ACK有什么用?
答:

follower每次在同步数据的时候,会从最大的zxid(也就是本次leader发过来的zxid)开始向下递归,去判断跟leader的每个zxid所对应的数据是否一致,不一致则同步过来,直到发现和leader所对应的数据相同为止。

从这里也能看出,zk的所谓的一致性是 最终一致性 而不是 实时一致性

Observer的数量问题

Observer不是越多越好,通常是与Follower的数量相同。因为follower一旦变多,将会增加系统的同步压力。

Observer与Follower的异同

Observer与Flollower在功能上基本相同,但是在同步的时候,如果Follower已经同步完成了,那么无论Observer是否同步完成都要结束同步,没有完成同步的Observer将无法对外提供服务。

在Leader当中会对他们两个分别维护两个功能相同列表(4个列表哦),一个是记录所有的observer和follower(all列表),一个是记录完成同步的Observer和Follower(service列表)。

对于没有完成同步的observer我认为通常是因为网络波动的原因所致,所以zk在leader和learner(包括observer和follower)之间设计了一种心跳机制,没有同步完成的observer会通过心跳来连接leader,一旦连接上了就开始同步数据,数据同步完成后返回个leader一个ACK,leader会将其加入service列表,此时Observer就会处于Observing状态,就是能够正常向外部提供服务了。

没有完成同步的Follower不会处于Observing状态,当然也不会在leader的service列表当中。只有处于Observing状态的observer能够向外提供服务,这个状态通过Follower与Leader之间的心跳来进行维护(上边已经说了是怎么进行维护的)

恢复模式的三个原则

首先,说说进入恢复模式的三种场景。

  1. 集群启动,leader与其他learner的连接数没有过半

  2. leader宕机,并且已经向其他learner同步了一些事务请求

  3. leader宕机,没有向其他learner同步事务请求,然后leader又起来了

以上三种场景,每种场景进入恢复模式的时候都会对应一个原则

  1. Leader主动出让原则

    第一种场景下,leader你都跟其他learner连不上了,你得主动出让自己的learner权利。如果任何一个learner发现自己与leader连不上了就会进入LOOKING状态,当有过半的learner处于LOOKING状态,将会重新选举leader。

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

    第二种场景下,会在已经同步完数据的follower中进行leader的选举,选举完成后,新的leader会用与更新广播算法相似的形式来向其他没有完成同步的follower进行数据同步。

    同步过程:

    follower会先向下递归,找到xid与新leader的xid相同并且内容也相同的项,然后再向上递归进行数据同步,知道同步到最大的xid。

  3. 被丢弃的事务不能再现

    第三种场景下,leader此时已经不再是leader,它只要作为一个follower向新的leader按照之前所说过的同步算法进行数据同步就好了。

leader选举(重点,还要阅读源码)

截屏2020-03-20下午8.13.58.png
截屏2020-03-20下午8.17.03.png

zk高可用集群的容灾设计

集群的数量的奇偶

7台和8台的集群理论上容灾效果是一样的,因为无论7台还是8台机器要想集群能够正常工作,都是遵循需要至少过半的机器没有宕机的原则,而7台或者8台要求过半的机器不宕机,最多能允许出现宕机的机器数量都是3台。所以容灾能力都一样,这个时候就要考虑,多家一台机器所提升的系统吞吐量是否有必要,有必要则选择7台,没必要就选择8台节省资源。

三机房部署

三个机房每个机房的机器数量都不超过zk集群的一半,这样任何一个机房出现问题,都不会影响集群的正常工作。

CAP定理

CAP 原则又称 CAP 定理,指的是在一个分布式系统中,Consistency(一致性)、Availability (可用性)、Partition tolerance(分区容错性),三者不可兼得。

  • 一致性(C):分布式系统中多个主机之间是否能够保持数据一致的特性。即,当系统数据发生更新操作后,各个主机中的数据仍然处于一致的状态。

  • 可用性(A):系统提供的服务必须一直处于可用的状态,即对于用户的每一个请求,系统总是可以在有限的时间内对用户做出响应。

  • 分区容错性(P):分布式系统在遇到任何网络分区故障时,仍能够保证对外提供满足一致性和可用性的服务。

对于分布式系统,网络环境相对是不可控的,出现网络分区是不可避免的,因此系统必 须具备分区容错性。但其并不能同时保证一致性与可用性。CAP 原则对于一个分布式系统来 说,只可能满足两项,即要么 CP,要么 AP

ZOOKEEPER技术内幕

数据模型Znode

截屏2020-03-26下午2.00.22.png

结点类型

  • 持久节点

  • 持久顺序节点

  • 临时节点

  • 临时顺序节点

结点状态

  • cZxid:CreatedZxid,表示当前znode被创建时的事务ID

  • ctime:CreatedTime,表示当前znode被创建的时间

  • mZxid:ModifiedZxid,表示当前znode最后一次被修改时的事务ID

  • mtime:ModifiedTime,表示当前znode最后一次被修改时的时间

  • pZxid:表示当前znode的子节点列表最后一次被修改时的事务ID。注意,只能是其子

    节点列表变更了才会引起pZxid的变更,子节点内容的修改不会影响pZxid。

  • cversion:ChildrenVersion,表示子节点的版本号。该版本号用于充当乐观锁。

  • dataVersion:表示当前znode数据的版本号。该版本号用于充当乐观锁。

  • aclVersion:表示当前znode的权限ACL的版本号。该版本号用于充当乐观锁。

  • ephemeralOwner:若当前znode是持久节点,则其值为0;若为临时节点,则其值为创

    建该节点的会话的SessionID。当会话消失后,会根据SessionID来查找与该会话相关的

    临时节点进行删除。

  • dataLength:当前znode中存放的数据的长度。

  • numChildren:当前znode所包含的子节点的个数。

ACL

ACL 全称为 Access Control List(访问控制列表),是一种细粒度的权限管理策略,可以针 对任意用户与组进行细粒度的权限控制。zk 利用 ACL 控制 znode 节点的访问权限,如节点 数据读写、节点创建、节点删除、读取子节点列表、设置节点权限等。

Zookeeper 的 ACL 分为三个维度:

  • 授权策略 scheme

  • 授权对象 id

  • 用户权限 permission。

授权策略

即如果用户想要访问zk的结点,要怎样验证他的权限。

在 zk 中最常用的有四种策略

  • IP

  • digest

  • world

  • super

授权对象id

授权对象指的是权限赋予的用户。不同的授权策略具有不同类型的授权对象。下面是各 个授权模式对应的授权对象 id。

  • ip

  • digest

  • world

  • Super

Watcher机制

zk 通过 Watcher 机制实现了发布/订阅模式

截屏2020-03-26下午2.16.30.png

你可能感兴趣的:(Zookeeper学习笔记)