Zookeeper 知识点整理

Zookeeper 是分布式协调服务,可以在分布式中共享配置,协调锁资源,提供命名服务等。

1. 数据模型

与Unix文件系统非常类似,可以看做是一颗树,每个节点叫做ZNode,每一个节点可以通过路径来标识。

ZNode包含数据,子节点的引用,访问权限。

  1. data:Znode存储的数据信息。
  2. ACL:记录Znode的访问权限,即哪些人或哪些IP可以访问本节点。
  3. stat:包含Znode的各种元数据,比如事务ID、版本号、时间戳、大小等等。
  4. child:当前节点的子节点引用,类似于二叉树的左孩子右孩子。

Zookeeper是为读多写少的场景所设计,所以ZNode不是用来存储大规模业务数据,而是用于存储少量的状态和配置信息,每个节点的数据最大不能超过1MB。

1.1 节点状态

状态属性描述
cZxidCreated ZXID,表示该节点被创建时的事务ID
ctimeCreated Time,表示该节点被创建的时间
mZxidModified ZXID,表示该节点最后一次被更新时的事务ID
mtimeModified Time,表示该节点最后一次被更新的时间
pZxid表示该节点的子节点列表最后一次被修改时的事务ID。只有子节点列表变更才会变更pZxid,子节点内容变更不影响pZxid
cversion子节点的版本号
dataVersion数据内容版本号
aclVersion节点的ACL版本号
ephemeralOwner创建改临时节点的会话的sessionID。如果该节点时持久节点,该属性值为0
dataLength数据内容长度
numChildren当前节点的子节点个数

1.2 类型

  1. 持久节点 (PERSISTENT):默认的节点类型,创建节点的客户端与Zookeeper断开连接后,该节点依旧存在 。
  2. 持久顺序节点(PERSISTENT_SEQUENTIAL):顺序节点,就是在创建节点时,Zookeeper根据创建的时间顺序给该节点名称进行编号。
  3. 临时节点(EPHEMERAL):和持久节点相反,当创建节点的客户端与Zookeeper断开连接后,临时节点会被删除。
  4. 临时顺序节点(EPHEMERAL_SEQUENTIAL): 结合临时节点和顺序节点的特点。在创建节点时,Zookeeper根据创建的时间顺序给该节点名称进行编号;当创建节点的客户端与zookeeper断开连接后,临时节点会被删除。

创建节点命令

  1. 持久节点:create path data
  2. 持久顺序节点:create -s path
  3. 临时节点:create -e path data
  4. 临时顺序节点:create -e -s path

2. Watcher

在ZooKeeper中允许客户端向服务端注册一个Watcher,当服务端的一些指定事件触发了这个Watcher,那么就会向指定客户端发送一个异步事件通知来实现分布式通知功能,该功能只能执行一次。

Watcher是注册在特定Znode上的监听器,监听节点的变化,主要用于监听节点的数据变化和子节点的增减变化。客户端在请求读操作的时候,可以选择是否设置Watcher。

监听命令

  1. 监听节点内容变化:get -e -w path
  2. 监听节点状态变化:stat -w path
  3. 监听该节点下所有子节点的增减:ls -w path

3. 事务ID

在ZooKeeper中,事务是指能够改变ZooKeeper服务器状态的操作,一般指节点创建与删除、节点内容更新和客户端会话创建与失效等操作。

对于每一个事务请求,ZooKeeper会分配一个全局唯一的事务ID,用ZXID来表示,通常是一个64位的数字。每一个ZXID对应一次更新操作,可从ZXID中了解到更新请求的全局顺序。

事务ID分为两部分:纪元(epoch)和计数器(counter)。epoch代表当前集群所属的哪个leader。

4. ZAB

Zookeeper集群是一主多从结构。

在更新数据时,首先更新到主节点,再同步到从节点;在读取数据时,直接读取任意从节点。

为了保证主从节点的数据一致性,Zookeeper采用了ZAB协议。

4.1 集群角色

  1. Leader:同一时间集群总只允许有一个Leader,提供对客户端的读写功能,负责将数据同步至各个节点;
  2. Follower:提供对客户端读功能,写请求则转发给Leader处理,当Leader崩溃失联之后参与Leader选举;
  3. Observer:充当观察者,观察集群的最新状态变化,并将状态变更同步过来。与Follower基本一致,提供对客户端读功能,不同的是不参与Leader选举。

4.2 节点状态

Zookeeper是通过自身的状态来区分自己所属的角色,来执行自己应该的任务。

  1. LOOKING:当节点认为群集中没有Leader,服务器会进入LOOKING状态,目的是为了查找或者选举Leader;
  2. FOLLOWING:Follower角色;
  3. LEADING:Leader角色;
  4. OBSERVING:Observer角色。

4.3 ZAB状态

整个ZAB协议主要包括崩溃恢复和消息广播两个过程, Zookeeper还给ZAB定义的4中状态,反应Zookeeper从选举到对外提供服务的过程中的四个步骤。

  1. ELECTION:集群进入选举状态,此过程会选出一个节点作为Leader角色;
  2. DISCOVERY:连接上Leader,响应Leader心跳,并且检测Leader的角色是否更改;
  3. SYNCHRONIZATION:整个集群都确认Leader之后,将会把Leader的数据同步到各个节点,保证整个集群的数据一致性,通过此步骤之后选举出的Leader才能执行真正职务;
  4. BROADCAST:过渡到广播状态,集群开始对外提供服务。

4.3.1 ELECTION(选举)

发生集群选举有两种情况:

  1. 服务启动的时候,整个集群没有Leader节点就会进入选举状态;
  2. 在服务运行中,可能会出现服务宕机、断电、网络延迟等情况,这时候Leader就不能再对外提供服务了,当其他节点通过心跳检测到Leader失联之后,集群也会进入选举状态。
4.3.1.1 服务器启动时期的Leader选举
  1. 发送投票。初始情况下,集群没有Leader,服务器都是LOOKING状态。服务器会先投给自己,再把这个投票发给集群的其他所有机器。投票包含服务器的myid和ZXID;
  2. 接收投票。服务器接收其他服务器的投票。首先会判断该投票的有效性,包括检查是否是本轮投票,是否来自LOOKING状态的服务器;
  3. 处理投票。服务器接收投票后进行处理,将其他服务器的投票和自己的投票进行比较,发送比较后的投票;
  4. 统计投票。投票完,服务器会统计所有投票。当有过半的服务器接收到了相同的投票信息,就算选出了Leader;
  5. 改变状态。确定了Leader,每个服务器更新自己的状态。如果是Leader,变更为LEADERING;如果是Follower,变更为FOLLOWING。
4.3.1.2 服务器运行期间的Leader选举

选出Leader一般不会再发生变化,除非Leader挂了,就会进入新一轮的选举。

  1. 改变状态。Leader挂了,除了Observer服务器,其余服务器变更为LOOKING状态,进入选举状态;
  2. 后续流程与服务器启动时期的Leader选举一致。发送投票,接收投票,处理投票,统计投票,改变状态。
4.3.1.3 投票比较规则
  1. 选高的纪元(epoch);
  2. 纪元(epoch)相同,选大的ZXID,ZXID越大代表该节点的数据越完整;
  3. 纪元(epoch)和ZXID都相等,比较serverId。serverId是配置Zookeeper集群所配置的,所以配置Zookeeper集群的时候可以把服务性能更高的集群的serverId配置大些,让性能好的机器担任Leader角色。

4.3.2 DISCOVERY(发现)

发现阶段,用于在从节点中发现最新的ZXID和事务日志。这是为了防止某些意外情况,比如因网络原因在上一阶段产生多个Leader的情况。

  1. Leader会接收所有Follower的纪元(epoch);
  2. Leader接收到过半的epoch值后,从中选出最大的epoch,然后对其加1,在分发给各个Follower;
  3. 各个Follower收到全新的epoch后,返回ACK给Leader,带上各自最大的ZXID和历史事务日志;
  4. Leader接收到过半的ACK后,从中选出最大的ZXID,并更新自身的历史事务日志。

4.3.3 SYNCHRONIZATION(同步)

同步阶段,把Leader刚才收集得到的最新历史事务日志,同步给集群中所有的Follower。

只有当半数Follower同步成功,这个准Leader才能成为正式的Leader。

  1. Leader将最新的历史事务日志,同步给集群中的所有Follower;
  2. Follower处理事务,反馈给Leader;
  3. Leader接收到过半Follower的反馈信息后,向所有Follower发送Commit信息。Leader完成同步;
  4. Follower收到Leader的Commit消息,提交所有事务。Follower完成同步。

4.3.4 BROADCAST(广播)

完成同步阶段,就可以接收客户端新的事务请求,并进行广播。

  1. Leader接收客户端新的事务请求,生成事务并根据ZXID顺序,广播给所有Follower;
  2. Follower根据消息接受先后次序(由一个FIFO的队列维护)来处理Leader的事务,写入本地磁盘,写入成功后返回ACK给Leader;
  3. Leader收到过半的ACK之后,开始提交本事务,并广播事务提交信息;
  4. Follower接收Leader的Commit消息后,开始提交事务。

在正常运行中,会一直处于该阶段反复进行消息广播。如果Leader崩溃或其他原因导致Leader缺失,那么会重新进行选举,选举出新Leader。

Zookeeper通过类二阶段提交来保证集群中数据的一致性,因为只需要收到过半的ACK就可以提交事务,所以Zookeeper的数据并不是强一致性。

ZAB在广播状态中保证了消息可靠传递,事务全局和因果有序:

  1. 服务器使用TCP协议进行通信,保证在网络传输的可靠性和有序性;
  2. 服务器维护一个FIFO的队列,保证全局有序性;
  3. 全局递增的ZXID,保证因果有序性。

5. 用途

5.1 数据发布/订阅(统一配置管理)

系统A,B,C共用的配置放在Zookeeper的某个ZNode上,再监听该ZNode,发生变更及时响应。

5.2 统一命名服务

给某个资源取个名字,然后放在Zookeeper上的某个ZNode上,通过名字获取资源。

5.3 分布式锁

创建一个持久节点当作锁,系统A,B,C要抢锁,就要在该节点下创建临时顺序节点。

流程
Zookeeper保证了系统A,B,C创建临时节点的顺序性,假设创建的顺序为A,B,C。

然后系统A,B,C会判断是否抢到了锁。
系统A:获取该节点下所有子节点,比较后发现自己的顺序最小,拿到锁。
系统B:获取该节点下所有子节点,比较后发现自己的顺序不是最小,就监听比自己靠前的第一个节点,即系统A创建的节点。
系统C:获取该节点下所有子节点,比较后发现自己的顺序不是最小,就监听比自己靠前的第一个节点,即系统B创建的节点。

系统A执行完后删除自己创建的节点,或系统A奔溃断开连接,节点自动删除。
通过监听,系统B发现系统A创建的节点已删除,自己是最小的节点,于是就拿到锁。以此类推。

优点

  1. Zookeeper定位就是分布式协调,强一致性。锁的模型健壮、简单易用、适合做分布式锁;
  2. 如果获取不到锁,只需要添加一个监听器就可以了,性能消耗较小。

缺点

  1. 性能没缓存服务高;
  2. 创建和删除节点只能在Leader服务器,然后将数据同步道所有Follower服务器上;
  3. 网络抖动导致连接断开,临时节点被删除;
  4. 如果有较多的客户端频繁的申请加锁、释放锁,对于zk集群的压力会比较大。

5.4 集群状态

各系统在持久节点下创建临时节点。如果需要选举,创建临时顺序节点。

参考:
从Paxos到Zookeeper 分布式一致性原理与实践
漫画:什么是ZooKeeper?
漫画:如何用Zookeeper实现分布式锁?
面试官:说一下Zookeeper的ZAB协议?
分布式锁之Zookeeper
分布式锁用 Redis 还是 Zookeeper?
ZooKeeper 的应用场景

©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页