zookeeper总结

zookeeper的应用案例:
Hbase:使用zookeeper进行master选举,服务间协调。
Solr:使用zookeeper进行集群管理,leader选举,配置管理。
dubbo:服务注册
mycat:集群管理,配置管理。
sharding-sphere:集群管理,配置管理。
kafka:存储每个partition的最后读取的offset值。(最新版本kafka去掉了对zookeeper的依赖。)

zookeeper的同类产品:
consul、etcd、doozer。

第三方客户端:
zkclient、Curator

zookeeper中的zab协议:
面试中问的最多:zookeeper在什么情况下服务会不可用啊?类似这些。
https://www.cnblogs.com/veblen/p/10985676.html

1. 什么是 ZAB 协议? ZAB 协议介绍

1、ZAB 协议全称:Zookeeper Atomic Broadcast(Zookeeper 原子广播协议)。

2、Zookeeper 是一个为分布式应用提供高效且可靠的分布式协调服务。在解决分布式一致性方面,Zookeeper 并没有使用 Paxos ,而是采用了 ZAB 协议。

3、ZAB 协议定义:ZAB 协议是为分布式协调服务 Zookeeper 专门设计的一种支持 ****崩溃恢复原子广播 协议。下面我们会重点讲这两个东西。

4、基于该协议,Zookeeper 实现了一种 主备模式 的系统架构来保持集群中各个副本之间 数据一致性。具体如下图所示:

image

上图显示了 Zookeeper 如何处理集群中的数据。所有客户端写入数据都是写入到 主进程(称为 Leader)中,然后,由 Leader 复制到备份进程(称为 Follower)中。从而保证数据一致性。从设计上看,和 Raft 类似。

那么复制过程又是如何的呢?

复制过程类似 2PC,ZAB 只需要 Follower 有一半以上返回 Ack 信息就可以执行提交,大大减小了同步阻塞。也提高了可用性。

简单介绍完,开始重点介绍 消息广播崩溃恢复整个 Zookeeper 就是在这两个模式之间切换。 简而言之,当 Leader 服务可以正常使用,就进入消息广播模式,当 Leader 不可用时,则进入崩溃恢复模式。

2. 消息广播

ZAB 协议的消息广播过程使用的是一个原子广播协议,类似一个 二阶段提交过程。对于客户端发送的写请求,全部由 Leader 接收,Leader 将请求封装成一个事务 Proposal,将其发送给所有 Follwer ,然后,根据所有 Follwer 的反馈,如果超过半数成功响应,则执行 commit 操作(先提交自己,再发送 commit 给所有 Follwer)。

基本上,整个广播流程分为 3 步骤:

1、将数据都复制到 Follwer 中

image

2、等待 Follwer 回应 Ack,最低超过半数即成功

image

3、当超过半数成功回应,则执行 commit ,同时提交自己

image

通过以上 3 个步骤,就能够保持集群之间数据的一致性。实际上,在 Leader 和 Follwer 之间还有一个消息队列,用来解耦他们之间的耦合,避免同步,实现异步解耦。

还有一些细节:

1、Leader 在收到客户端请求之后,会将这个请求封装成一个事务,并给这个事务分配一个全局递增的唯一 ID,称为事务ID(ZXID),ZAB 兮协议需要保证事务的顺序,因此必须将每一个事务按照 ZXID 进行先后排序然后处理。

2、在 Leader 和 Follwer 之间还有一个消息队列,用来解耦他们之间的耦合,解除同步阻塞。

3、zookeeper集群中为保证任何所有进程能够有序的顺序执行,只能是 Leader 服务器接受写请求,即使是 Follower 服务器接受到客户端的请求,也会转发到 Leader 服务器进行处理。

4、实际上,这是一种简化版本的 2PC,不能解决单点问题。等会我们会讲述 ZAB 如何解决单点问题(即 Leader 崩溃问题)。

3. 崩溃恢复

刚刚我们说消息广播过程中,Leader 崩溃怎么办?还能保证数据一致吗?如果 Leader 先本地提交了,然后 commit 请求没有发送出去,怎么办?

实际上,当 Leader 崩溃,即进入我们开头所说的崩溃恢复模式(崩溃即:Leader 失去与过半 Follwer 的联系)。下面来详细讲述。

假设1:Leader 在复制数据给所有 Follwer 之后崩溃,怎么办? 假设2:Leader 在收到 Ack 并提交了自己,同时发送了部分 commit 出去之后崩溃怎么办?

针对这些问题,ZAB 定义了 2 个原则:

1、ZAB 协议确保那些已经在 Leader 提交的事务最终会被所有服务器提交。 2、ZAB 协议确保丢弃那些只在 Leader 提出/复制,但没有提交的事务。

所以,ZAB 设计了下面这样一个选举算法:能够确保提交已经被 Leader 提交的事务,同时丢弃已经被跳过的事务。

针对这个要求,如果让 Leader 选举算法能够保证新选举出来的 Leader 服务器拥有集群总所有机器编号(即 ZXID 最大)的事务,那么就能够保证这个新选举出来的 Leader 一定具有所有已经提交的提案。 而且这么做有一个好处是:可以省去 Leader 服务器检查事务的提交和丢弃工作的这一步操作。

image

这样,我们刚刚假设的两个问题便能够解决。假设 1 最终会丢弃调用没有提交的数据,假设 2 最终会同步所有服务器的数据。这个时候,就引出了一个问题,如何同步?

4. 数据同步

当崩溃恢复之后,需要在正式工作之前(接收客户端请求),Leader 服务器首先确认事务是否都已经被过半的 Follwer 提交了,即是否完成了数据同步。目的是为了保持数据一致。

当所有的 Follwer 服务器都成功同步之后,Leader 会将这些服务器加入到可用服务器列表中。

实际上,Leader 服务器处理或丢弃事务都是依赖着 ZXID 的,那么这个 ZXID 如何生成呢?

答:在 ZAB 协议的事务编号 ZXID 设计中,ZXID 是一个 64 位的数字,其中低 32 位可以看作是一个简单的递增的计数器,针对客户端的每一个事务请求,Leader 都会产生一个新的事务 Proposal 并对该计数器进行 + 1 操作。

而高 32 位则代表了 Leader 服务器上取出本地日志中最大事务 Proposal 的 ZXID,并从该 ZXID 中解析出对应的 epoch 值,然后再对这个值加一。

image

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

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

5.zookeeper集群leader选举

zookeeper的选举算法是可以自己实现的。所以需要满足一些要求:
1.选出的leader 节点上要持有最高的zxid。
2.过半数节点同意。

内置现实的选举算法:leaderElection,FastLeaderElection,AuthFastLeaderElection.

选举机制中的概念:
1.服务器id:myid
2.事务id:服务器中存放的最大Zxid
3.逻辑始终:发起的投票轮数计数
4.选举状态:
Looking:竞选状态。
Following:随从状态,参与投票。
Observing:观察状态,不参与投票。
Leading,领导者状态。

leader选举时,服务不可用。,因为要保证有序性,才能保证一致性。

6. ZAB协议总结

ZAB 协议和我们之前看的 Raft 协议实际上是有相似之处的,比如都有一个 Leader,用来保证一致性(Paxos 并没有使用 Leader 机制保证一致性)。再有采取过半即成功的机制保证服务可用(实际上 Paxos 和 Raft 都是这么做的)。

ZAB 让整个 Zookeeper 集群在两个模式之间转换,消息广播和崩溃恢复,消息广播可以说是一个简化版本的 2PC,通过崩溃恢复解决了 2PC 的单点问题,通过队列解决了 2PC 的同步阻塞问题。

而支持崩溃恢复后数据准确性的就是数据同步了,数据同步基于事务的 ZXID 的唯一性来保证。通过 + 1 操作可以辨别事务的先后顺序。

面试题:当从节点都响应了leader节点的请求了,leader节点在发送完commit指令后,立马来了一条读取的请求落到了从节点上,请问是修改前的值还是修改后的值?
答:修改前的值,因为还没从节点还没收到commit指令,所以还是之前的值。(考点:zookeeper是顺序一致性。)

应用场景:

1.配置中心

1.一个配置文件一个znode;将配置文件存放在一个节点上,客户端去取配置文件。
2.一个配置项一个znode:将某个配置项放在一个节点上。多个配置项的话,客户端取多个znode的值。

2.命名服务

命名服务

如何实现服务A可以动态得到服务B的调用地址?
A服务上线之后,添加一个watch去监听serviceB的状态。当b服务上线的时候。b服务会在zookeeper创建一个节点,并往节点内写入自身的地址。A之前的监听到节点的更改,从而获取服务B的调用地址。

3.master选举

image.png

4.分布式队列

分布式队列实现原理

5.分布式锁

分布式锁实现方式一

这种以创建临时节点的方式来实现分布式锁,主要的问题是,如果有很多的客户端都来抢这个lock,一旦这个之前抢到节点的客户端释放了这个节点,或者这个客户端挂了。那么其余的客户端都会接收到信息,然后去抢这个节点的创建权。但最终只有一个节点能抢成功。导致了性能的浪费。这就是我们所说的惊群效应

分布式锁实现方式二

在实现分布式锁和master选举的场景下。要注意加锁的情况,得考虑可重入。

你可能感兴趣的:(zookeeper总结)