zookeeper最新(zookeeper370)
本篇文章给大家谈谈zookeeper最新,以及zookeeper370对应的知识点,希望对各位有所帮助,不要忘了收藏本站喔。
本文目录一览:
- 1、Zookeeper算法原理
- 2、zookeeper数据持久化
- 3、Zookeeper深入原理(3) - Zab协议
- 4、zookeeper与eureka区别
- 5、直观理解:Zookeeper分布式一致性协议ZAB
Zookeeper算法原理
zk算法的演进过程
1.Write-all-read-one
先讨论最简单的副本控制规则
Write-all-read-one(简称 WARO)是一种最简单的副本控制规则,顾名思义即在更新时写所有
的副本, 只有在所有的副本上更新成功,才认为更新成功, 从而保证所有的副本一致,这样在读取数据时可以读任一副本上的数据。
先做这样的约定 :更新操作(write)是一系列顺序的过程,通过其他机制
确定更新操作的顺序(例如 primary-secondary 架构中由 primary 决定顺序),每个更新操作记为 wi,
i 为更新操作单调递增的序号,每个 wi执行成功后副本数据都发生变化,称为不同的数据版本,记作 vi。假设每个副本都保存了历史上所有版本的数据。
假设有一种 magic 的机制,当某次更新操作 wi一旦在所有 N 个副本上都成功,此时 全局都能知
道这个信息(现实情况是比较难的) ,此后读取操作将指定读取数据版本为 vi的数据,称在所有 N 个副本上都成功的更新操作为“成功提交的更新操作”,称对应的数据为“成功提交的数据”。 在 WARO 中,如果某次更新操作 wi在某个副本上失败,此时该副本的最新的数据只有 vi-1,由于不满足在所有 N 个副本上都成功,
则 wi 不是一个“成功提交的更新操作”,此时,虽然其他 N-1 个副本上最新的数据是 vi,但 vi不是一个“成功提交的数据”,最新的成功提交的数据只是 vi-1 。
在工程实践中,这种 magic 的机制往往较难实现或效率较低。通常实现这种 magic 机制的方式就是 将版本号信息存放到某个或某组元数据服务器上 。假如更新操作非常频繁,那么记录更新成功的版本号 vi的操作将成为一个关键操作,容易成为瓶颈。另外,为了实现强一致性,在读取数据链陵辩的前必须首先读取元数据中的版本号,在大压力下也容易因为元数据服务器的性能造成瓶颈。
缺点:
WARO 的可用性。 由于更新操作需要在所有的 N 个副本上都成功,更新操作才能成功,所以一旦有一个副本异常,更新操作失败,更新服务不可用。对于更新服务,虽然有 N 个副本,
但系统无法容忍任何一个副本异常。另一方面, N 个副本中只要有一个副本正常,系统就可以提供读服务。对于读服务而言,当有 N 个副本时,系统可以容忍 N-1 个副本异常。
从上述分析可以发现 WARO 读服务的可用性较高,但更新服务的可用性不高 ,甚至虽然使用了
副本,但更新服务的可用性等效于没有副本.
2.Quorum 机制
将 WARO 的条件进行松弛,从而汪郑使得可以在 读写服务可用性之间做折中 ,得出 Quorum 机制.
在 Quorum 机制下,当某次更新操作 wi一旦在所有 N 个副本中的 W 个副本上都成功,则就称
该更新操作为“成功提交的更新操作”,称对应的数据为“成功提交的数据”。令 RN-W,由于更新
操作 wi仅在 W 个副本上成功,所以在读取数据时,最多需要读取 R 个副本则一定能读到 wi 更棚缺新后的数据 vi 。如果某次更新 wi在 W 个副本上成功,由于 W+RN,任意 R 个副本组成的集合一定与成功的 W 个副本组成的集合有交集,所以读取 R 个副本一定能读到 wi更新后的数据 vi。
例一:
某系统有 5 个副本, W=3, R=3,最初 5 个副本的数据一致,都是 v1, 某次更新操作
w2 在前 3 副本上成功,副本情况变成(v2 v2 v2 v1 v1)。此时, 任意 3 个副本组成的集合中一定包括v2。
例二:
N=5, W=2, R=3 时,若 4 个副本异常,更新操作始终无法完成。若 3 个副本异常时,
剩下的两个副本虽然可以提供更新服务,但对于读取者而言,在缺乏某些 magic 机制的,即如果读取者不知道当前最新已成功提交的版本是什么的时候,仅仅读取 2 个副本并不能保证一定可以读到最新的已提交的数据。
得出一个简单的结论:
仅 仅依赖 quorum 机制 是无法保证强一致性的。因为仅有 quorum 机制时 无法确定最新已成功提交的版本号 ,除非将最新已提交的版本号作为元数据由特定的元数据服务器或元数据集群管理,否则很难确定最新成功提交的版本号。
Quorum 机制只需成功更新 N 个副本中的 W 个,在读取 R 个副本时,一定可以读到 最新的成功
提交的数据。 但由于有不成功的更新情况存在,仅仅读取 R 个副本却不一定能确定哪个版本的数据是最新的已提交的数据(简而言之,就是说我读到的结果中包含了v1,v2我可以肯定最新的数据一定是他们两种的一个,但我却没办法确定是哪一个的)
例三:
在 N=5, W=3, R=3 的系统中,某时刻副本最大版本号为(v2 v2 v2 v1 v1)。注意,这里继续假设有 v2 的副本也有 v1,上述列出的只是最大版本号。此时,最新的成功提交的副本应该
是 v2,因为从全局看 v2已经成功更新了 3 个副本。 读取任何 3 个副本,一定能读到 v2。 但仅读 3 个副本时,有可能读到(v2 v1 v1)。 此时,由于 v2蕴含 v1, 可知 v1是一个成功提交的
版本, 但却不能判定 v2一定是一个成功提交的版本。 这是因为 ,假设**副本最大版本号为(v2 v1 v1 v1 v1), 当读取 3 个副本时也可能读到v2 v1 v1) ,此时 v2是一个未成功提交的版本。 所
以在本例中,仅仅读到(v2 v1 v1)时,可以肯定的是最新的成功提交的数据要么是 v1要么是 v2,却没办法确定究竟是哪一个。
对于一个强一致性系统,应该始终读取返回最新的成功提交的数据,在 quorum 机制下,要达
到这一目的需要对读取条件做进一步加强。
1. 限制提交的 更新操作必须严格递增 ,即只有在前一个更新操作成功提交后才可以提交后一
个更新操作,从而成功提交的数据版本号必须是连续增加的。
2. 读取 R 个副本,对于 R 个副本中版本号最高的数据,
2.1 若已存在 W 个,则该数据为最新的成功提交的数据
2.2 若存在个数据少于 W 个, 假设为 X 个, 则继续读取其他副本,直若成功读取到 W 个
该版本的副本,则该数据为最新的成功提交的数据;如果在所有副本中该数据的个数肯定不满
足 W 个,则 R 中版本号第二大的为最新的成功提交的副本。
例四:
依旧接例三,在读取到(v2 v1 v1)时,继续读取剩余的副本,若读到剩余两个副本为(v2 v2)则 v2 是最新的已提交的副本;若读到剩余的两个副本为(v2 v1)或(v1 v1)则 v1是最新成功提交的版本;若读取后续两个副本有任一超时或失败,则无法判断哪个版本是最新的成功提交的版本。
可以看出,在单纯使用 Quorum 机制时,若要确定最新的成功提交的版本,最多需要读取 R+
(W-R-1)=N 个副本,当出现任一副本异常时,读最新的成功提交的版本这一功能都有可能不可用。
实际工程中,应该尽量通过其他技术手段,回避通过 Quorum 机制读取最新的成功提交的版本。例如,当 quorum 机制与 primary-secondary 控制协议结合使用时,可以通过读取 primary 的方式读取到最新的已提交的数据。
在 primary-secondary 协议中,当 primary 异常时,需要选择出一个新的 primary,之后 secondary副本与 primary 同步数据。 通常情况下,选择新的 primary 的工作是由某一中心节点完成的,在引入quorum 机制后,常用的 primary 选择方式与读取数据的方式类似,即中心节点读取 R 个副本,选择R 个副本中版本号最高的副本作为新的 primary。新 primary 与至少 W 个副本完成数据同步后作为新的 primary 提供读写服务。首先, R 个副本中版本号最高的副本一定蕴含了最新的成功提交的数据。再者,虽然不能确定最高版本号的数是一个成功提交的数据,但新的 primary 在随后与 secondary 同步数据,使得该版本的副本个数达到 W,从而使得该版本的数据成为成功提交的数据。
以上这段其实就是zk的原理
简述下就是先用Quorum 机制选择出primary(版本号最高的,版本号是严格递增的),然后再用primary-secondary来同步数据,(我一定可以读取到版本号最高的,虽然此时有可能是已提交也有可能为未提交),但我同步之后可以保证该版本号的副本数达到w,从而使得该版本号的数据成为成功提交的数据.
例五:
在 N=5, W=3, R=3 的系统中,某时刻副本最大版本号为(v2 v2 v1 v1 v1),此时 v1是
系统的最新的成功提交的数据, v2 是一个处于中间状态的未成功提交的数据。假设此刻原 primary副本异常,中心节点进行 primary 切换工作。 这类“中间态”数据究竟作为“脏数据”被删除,还是作为新的数据被同步后成为生效的数据,完全取决于这个数据能否参与新 primary 的选举。此时有以下两种情况
情况一:
若中心节点与其中 3 个副本通信成功,读取到的版本号为(v1 v1 v1),则任
选一个副本作为 primary,新 primary以 v1 作为最新的成功提交的版本并与其他副本同步,当与第 1、第 2 个副本同步数据时,由于第 1、第 2 个副本版本号大于 primary,属于脏数据,删除脏数据,然后重新同步。
情况二:
若中心节点与其他 3 个副本通信成功,读取到的版本号为(v2 v1 v1), 则选取版本号为v2 的副本作为新的 primary,之后,一旦新 primary 与其他 2 个副本完成数据同步,则符合 v2 的副本个数达到 W 个,成为最新的成功提交的副本,新 primary 可以提供正常的读写服务。
一致性算法在实现状态机这种应用时,有以下常见的问题:
1.1 一般的leader选举过程
选举的轮次
1.2 leader选举的效率
1.3 加入一个已经完成选举的集群
怎么发现已完成选举的leader?
1.4 leader选举的触发
3.3.2 异常过程的顺序
follower挂掉又连接
raft与zk的对比
1 leader选举
为什么要进行leader选举?
在实现一致性的方案,可以像base-paxos那样不需要leader选举,这种方案达成一件事情的一致性还好,面对多件事情的一致性就比较复杂了,所以通过选举出一个leader来简化实现的复杂性。
1.1 一般的leader选举过程
更多的有2个要素:
1.1.1 选举投票可能会多次轮番上演,为了区分,所以需要定义你的投票是属于哪个轮次的。
他们都需要在某个轮次内达成过半投票来结束选举过程
1.1.2 投票PK的过程,更多的是日志越新越多者获胜
在选举leader的时候,通常都希望
选举出来的leader至少包含之前全部已提交的日志
自然想到包含的日志越新越大那就越好。
通常都是比较最后一个日志记录,如何来定义最后一个日志记录?
有2种选择,一种就是所有日志中的最后一个日志,另一种就是所有已提交中的最后一个日志。目前Raft和ZooKeeper都是采用前一种方式。日志的越新越大表示:轮次新的优先,然后才是同一轮次下日志记录大的优先
ZooKeeper:peerEpoch大的优先,然后zxid大的优先
但是有一个问题就是:通过上述的日志越新越大的比较方式能达到我们的上述希望吗?
特殊情况下是不能的,这个特殊情况详细可参见我们上面描述的
这个案例就是这种比较方式会 选举出来的leader可能并不包含已经提交的日志(和我们例三分析的一样) ,而Raft的做法则是对于日志的提交多加一个限制条件,即不能直接提交之前term的已过半的entry,即把这一部分的日志限制成未提交的日志,从而来实现上述的希望。
ZooKeeper呢?会不会出现这种情况?又是如何处理的?
ZooKeeper是不会出现这种情况的,因为ZooKeeper在每次leader 选举完成之后,都会进行数据之间的同步纠正,所以每一个轮次,大家都日志内容都是统一的
而Raft在leader选举完成之后没有这个同步过程,而是靠之后的AppendEntries RPC请求的一致性检查来实现纠正过程,则就会出现上述案例中隔了几个轮次还不统一的现象
1.2 leader选举的效率
Raft中的每个server在某个term轮次内只能投一次票,哪个candidate先请求投票谁就可能先获得投票,这样就可能造成split vote,即各个candidate都没有收到过半的投票,Raft通过candidate设置不同的超时时间,来快速解决这个问题,使得先超时的candidate(在其他人还未超时时)优先请求来获得过半投票**
ZooKeeper中的每个server,在某个electionEpoch轮次内,可以投多次票,只要遇到更大的票就更新,然后分发新的投票给所有人。这种情况下不存在split vote现象,同时有利于选出含有更新更多的日志的server,但是选举时间理论上相对Raft要花费的多。
1.3 加入一个已经完成选举的集群
1.3.1 怎么发现已完成选举的leader?
一个server启动后(该server本来就属于该集群的成员配置之一,所以这里不是新加机器),如何加入一个已经选举完成的集群
1.3.2 加入过程是否阻塞整个请求?
这个其实还要 看对日志的设计是否是连续的
如果 是连续的,则leader中只需要保存每个follower上一次的同步位置,这样在同步的时候就会自动将之前欠缺的数据补上,不会阻塞整个请求过程(****所以为什么redis的选举算法是raft?毕竟redis单线程****)
如果 不是连续的,则在确认follower和leader当前数据的差异的时候,是需要获取leader当前数据的读锁,禁止这个期间对数据的修改。差异确定完成之后,释放读锁,允许leader数据被修改,每一个修改记录都要被保存起来,最后一一应用到新加入的follower中。
1.4 leader选举的触发
触发一般有如下2个时机
2 上一轮次的leader
2.1 上一轮次的leader的残留的数据怎么处理?
首先看下上一轮次的leader在挂或者失去leader位置之前,会有哪些数据?
一个日志是否被过半复制,是否被提交,这些信息是由leader才能知晓的,那么下一个leader该如何来判定这些日志呢?
下面分别来看看Raft和ZooKeeper的处理策略:
Raft的保守策略更多是因为Raft在leader选举完成之后,没有同步更新过程来保持和leader一致(在可以对外处理请求之前的这一同步过程)。而ZooKeeper是有该过程的
2.2 怎么阻止上一轮次的leader假死的问题
这其实就和实现有密切的关系了。
3 请求处理流程
3.1 请求处理的一般流程
这个过程对比Raft和ZooKeeper基本上是一致的,大致过程都是过半复制
先来看下Raft:
再来看看ZooKeeper:
备注:数据同步过程就有点类似于两阶段提交了。
假装是图2
3.2 日志的连续性问题
在需要保证顺序性的前提下,在利用一致性算法实现状态机的时候,到底是实现连续性日志好呢还是实现非连续性日志好呢?
还有在复制和提交的时候:
其他有待后续补充
3.3 如何保证顺序
具体顺序是什么?
这个就是先到达leader的请求,先被应用到状态机。这就需要看正常运行过程、异常出现过程都是怎么来保证顺序的
3.3.1 正常同步过程的顺序
3.3.2 异常过程的顺序保证
如follower挂掉又重启的过程:
ZooKeeper:重启之后,需要和当前leader数据之间进行差异的确定,同时期间又有新的请求到来,所以需要暂时获取leader数据的读锁,禁止此期间的数据更改,先将差异的数据先放入队列,差异确定完毕之后,还需要将leader中已提交的议案和未提交的议案也全部放入队列,即ZooKeeper的如下2个集合数据
ConcurrentMapLong, Proposal outstandingProposals
ConcurrentLinkedQueueProposal toBeApplied
如果是leader挂了之后,重新选举出leader,会不会有乱序的问题?
3.4 请求处理流程的异常
一旦leader发给follower的数据出现超时等异常
4 分区的应对
目前ZooKeeper和Raft都是过半即可,所以对于分区是容忍的。如5台机器,分区发生后分成2部分,一部分3台,另一部分2台,这2部分之间无法相互通信
其中,含有3台的那部分,仍然可以凑成一个过半,仍然可以对外提供服务,但是它不允许有server再挂了,一旦再挂一台则就全部不可用了。
含有2台的那部分,则无法提供服务,即只要连接的是这2台机器,都无法执行相关请求。
所以ZooKeeper和Raft在一旦分区发生的情况下是是牺牲了高可用来保证一致性,即CAP理论中的CP。但是在没有分区发生的情况下既能保证高可用又能保证一致性,所以更想说的是所谓的CAP二者取其一,并不是说该系统一直保持CA或者CP或者AP,而是一个会变化的过程。在没有分区出现的情况下,既可以保证C又可以保证A,在分区出现的情况下,那就需要从C和A中选择一样。ZooKeeper和Raft则都是选择了C。
zookeeper数据持久化
zookeeper靠snapshot日志和log日志进行数据的持久化和恢复工作
SNAPSHOT
snapshot机制定期将内存数据序列化到snapshot.xx(zxid)文件,数量受基本配置autopurge.snapRetainCount控制,默认是3
频率受高级配置snapCount控制:默认是10w,不过不是所有节点都是达到10w就开始写snapshot,
因为写snapshot的过程中写请求是会被卡住的,所以又有了另外一个内部算法,即取随机数
[snapCount/2+1, snapCount],在这个范围内就有可能触发重写snapshot.
LOG
另亩兄旦外生成的log.xxx(zxid) 则是实时的日志记录尘弊,也叫做WAL(write ahead log)预写日志.
默认64M,如果在生成新的snapshot前,文件被写满,就会扩一倍大小;
默认预分配大小受高级配置迅扰preAllocSize控制,如果snapCount很小,这个值也可以减小;
snapshot.xx和log.xx的xx 都是16进制,
300M snapshot.27c343ef9a
300M snapshot.27c342718c
300M snapshot.27c34114f6
300M snapshot.27c3403a76
300M snapshot.27c33f2cbe
300M snapshot.27c33dc303
300M snapshot.27c33c83a1
300M snapshot.27c33b3960
13M log.27c342718e
13M log.27c33dc305
12M log.27c34114f8
12M log.27c33b39d4
11M log.27c33c83a3
11M log.27c33a0eef
9.2M log.27c33f2cc0
7.4M log.27c3403a78
4.0K currentEpoch
4.0K acceptedEpoch
2.5M log.27c343ef9d
log.zxid的zxid是log文件中第一条事务的ZXID,ZXID规则为前32位(4字节)为leader周期,后32字节为事务请求序列,所以通过事务日志名称就可以轻松的知道当前的leader周期与每个文件所属的leader周期.(根据日志的最新修改时间)
这2类文件可以分不同的目录部署, 受高级配置dataLogDir控制,官方介绍:
Having a dedicated log device has a large impact on throughput and stable latencies. It is highly recommended to dedicate a log device and set dataLogDir to point to a directory on
that device, and then make sure to point dataDir to a directory not residing on that device.
————建议是logDir存放log.xx文件,因为写入频率比较高,可以挂性能比较好的盘
事务日志文件和快照文件都是二进制数据, 这2个文件的查看方式可以看另外一篇博文
Zookeeper日志文件查看,具体结构分析
[img]Zookeeper深入原理(3) - Zab协议
Zab协议全称是 Zookeeper Atomic BroadCast (Zookeeper 原子广播),Zookeeper是通过Zab协议来保证分布式事务的一致性。
1.Zab协议是zookeeper专门设计的一种 支持崩溃恢复 的 原子广播协议, 是Zookeeper保证数据一致性的核心算法。
2.在Zookeeper当中依赖Zab协议来保证数据的一致性,基于这个协议,zookeeper实现了一种主备模型,(Leader+Follower)的架构在保证集群中各个副本之间数据的一致性。 Leader负责处理写事务请求,然后Leader将数据同步到Follower节点上。
3.zookeeper客户端会随机连接到集群中的一个节点上,如果是读请求,就会从当前节点进行读取数据,如果是写的请求,就会将事务请求提交到Leader节点,leader节点接收到事务提交,就会广播该事务,如果超过一半节点写入成功,那么该事务就会被提交。
1.Zab协议需要确保那些已经在leader服务器上提交的事务胡绝最终被所有服务器提交。
2.Zab协议需要确保那些在leader服务器上被提出而没有被提交的事务。
1.使用主进程(leader)来接受客户端并处理客户端的事务请求,并采用Zab的原子广播协议,将服务器数据变更的状态以事务提议的形式广播到所有的follower副本上去。
2.当主进程出现异常,整个zk集群依然能够正常运行。
Zab协议每个leader需要经过三个阶段:发现、同步、广播
发现 :要求Zookeeper集群必须选取出一个leader进程,同时leader需要维护一个follower可用客户端列表,将来客户端可以和这些follower进行通信。
同步 :Leader要将本身的数据与follower进行同步,实现多副本存储,也体现了CAP中的高可用和分区容错。follower将队列中未处理完的消息消费完成后,写入到本地日志中。
广播 :leader接受客户端提出的事务请求,将新的事务请求广播给follower节点。
Zab协议核心:定义了事务请求的处理方式。
1.所有的事务请求必须由一个全局唯一的服务器来协调处理(Leader 服务器),其余的服务器是follower服务器。
2.leader服务器负责将客户端提出的事务请求,转换成一个事务proposal,并将事务proposal分发给集群中follower服务器,也就是向所有follower节点发送数据广播请求。
3.分发之后leader服务器需要等待follower服务器的反馈,在Zab协议中,只要超过半数的follower服务器进行确认了,那么leader就会再次向所有的follower发送commit消息,要镇做绝求将上一个事务进行提交。
Zab协议包括两种模式: 崩溃恢复 和 消息广播
协议过程
当整个集群启动过程中,或者leader服务器出现宕机或者网络终端等异常时,Zab协议就会进入崩溃恢复模式,选举出新的leader。
当选举出新的leader之后,同时集群中有过半的服务器与该leader服务器完成了状态同御姿步(数据同步),Zab协议就会退出崩溃恢复模型,进入消息广播模式。
如果新增一台服务器加入集群中,当前集群中已经选举出leader,那么加入进来的服务器自动进入恢复模式,找到leader服务器进行状态同步,完成同步后,与其他follower一起参与到广播流程中。
Zookeeper集群中,数据副本的传递策略采用的是消息广播模式。Zab协议中Leader等待follower 的ACK反馈消息,当到达半数以上follower成功反馈即可,不需要等所有的follower全部反馈。
leader服务器出现宕机和网络原因等导致leader与过半的follower服务器不能联系,就会自动进入崩溃恢复模式。
在Zab协议中,为了保证程序的正常运行,整个恢复过程结束后需要重新选出一个leader服务器,因此Zab协议需要一个高效且可靠的算法,来保证快速选举出leader。
Leader算法不仅让leader自己知道自己已经被选取为leader,还需要让集群中的所有服务器快速的感知到选举出的新leader服务器。
崩溃恢复包括两个部分: Leader选举 和 数据恢复
Zab 协议如何保证数据一致性
假设两种异常情况:
1、一个事务在 Leader 上提交了,并且过半的 Folower 都响应 Ack 了,但是 Leader 在 Commit 消息发出之前挂了。
2、假设一个事务在 Leader 提出之后,Leader 挂了。
要确保如果发生上述两种情况,数据还能保持一致性,那么 Zab 协议选举算法必须满足以下要求:
Zab 协议崩溃恢复要求满足以下两个要求 :
1) 确保已经被 Leader 提交的 Proposal 必须最终被所有的 Follower 服务器提交 。
2) 确保丢弃已经被 Leader 提出的但是没有被提交的 Proposal 。
根据上述要求
Zab协议需要保证选举出来的Leader需要满足以下条件:
1) 新选举出来的 Leader 不能包含未提交的 Proposal 。
即新选举的 Leader 必须都是已经提交了 Proposal 的 Follower 服务器节点。
2) 新选举的 Leader 节点中含有最大的 zxid 。
这样做的好处是可以避免 Leader 服务器检查 Proposal 的提交和丢弃工作。
Zab 如何数据同步
1)完成 Leader 选举后(新的 Leader 具有最高的zxid),在正式开始工作之前(接收事务请求,然后提出新的 Proposal),Leader 服务器会首先确认事务日志中的所有的 Proposal 是否已经被集群中过半的服务器 Commit。
2)Leader 服务器需要确保所有的 Follower 服务器能够接收到每一条事务的 Proposal ,并且能将所有已经提交的事务 Proposal 应用到内存数据中。等到 Follower 将所有尚未同步的事务 Proposal 都从 Leader 服务器上同步过啦并且应用到内存数据中以后,Leader 才会把该 Follower 加入到真正可用的 Follower 列表中。
Zab 数据同步过程中,如何处理需要丢弃的 Proposal
在 Zab 的事务编号 zxid 设计中,zxid是一个64位的数字。
其中低32位可以看成一个简单的单增计数器,针对客户端每一个事务请求,Leader 在产生新的 Proposal 事务时,都会对该计数器加1。而高32位则代表了 Leader 周期的 epoch 编号。
epoch 编号可以理解为当前集群所处的年代,或者周期。每次Leader变更之后都会在 epoch 的基础上加1,这样旧的 Leader 崩溃恢复之后,其他Follower 也不会听它的了,因为 Follower 只服从epoch最高的 Leader 命令。
每当选举产生一个新的 Leader ,就会从这个 Leader 服务器上取出本地事务日志充最大编号 Proposal 的 zxid,并从 zxid 中解析得到对应的 epoch 编号,然后再对其加1,之后该编号就作为新的 epoch 值,并将低32位数字归零,由0开始重新生成zxid。
Zab 协议通过 epoch 编号来区分 Leader 变化周期 ,能够有效避免不同的 Leader 错误的使用了相同的 zxid 编号提出了不一样的 Proposal 的异常情况。
基于以上策略
当一个包含了上一个 Leader 周期中尚未提交过的事务 Proposal 的服务器启动时,当这台机器加入集群中,以 Follower 角色连上 Leader 服务器后,Leader 服务器会根据自己服务器上最后提交的 Proposal 来和 Follower 服务器的 Proposal 进行比对,比对的结果肯定是 Leader 要求 Follower 进行一个回退操作,回退到一个确实已经被集群中过半机器 Commit 的最新 Proposal 。
本文根据进行编写。
zookeeper与eureka区别
zookeeper与eureka区别:
1:zookeeper保证cp原则(一致性)而Eureka保证的是ap原则(可用性)
2:zookeeper在选举期间注册服务瘫痪不可用,而Eureka各个节点平等,只要一台就能保证服务可以,但查询到的猛银数据不一定是最新的,可以很好的应对网络故障导致的部分节点失联
3:zookeeper有header和follower角色(当header挂掉,会从剩下的follower里面选举一个header),Eureka各个节点平等
4:zookeeper采用半数存活原则(避免脑裂),Eureka采用自我保护机制来解决判肢分区问题
5:kafka就枝冲宴是使用的zookeeper作为注册中心,理论上Eureka更适合作为注册中心
直观理解:Zookeeper分布式一致性协议ZAB
ZAB是Zookeeper使用的分布式一致性协议,英文全称是:Zookeeper Atomic Broadcast,因此ZAB也称之为Zookeeper原子广播协议。在解决分布式一致性方面,Zookeeper并没有使用Paxos,而是采用了ZAB协议。基于ZAB协议,Zookeeper实现一种主备模式的系统架构来保持集群中主备副本之间数据的一致性。ZAB协议包括两种基本模式:消息广播(Message Broadcasting)和崩溃恢复(Leader Activation)。下面来详细介绍这两种基本模式的实现过程。
消息广播是Zookeeper用来保证写早缺入事务一致性的方法,在Zookeeper集群中,存在以下三种角色的节点:
Leader: Zookeeper集群的核心角色,在集群启动或崩溃恢复中通过Follower参与选举产生,为客户端提供读写服务,并对事务请求进行处理。
Follower: Zookeeper集群的核心角色,在集群启动或崩溃恢复中参加选举,没有被选上就是这个角色,为客户端提供读取服务,也就是处理非事务请求,Follower不能处理事务请求,对于收到的事务请求会转发给Leader。
Observer: 观察者角色,不参加选举,为客户端提供读取服务,处理非事务请求,对于收到的事务请求会转发给Leader。使用Observer的目的是宽液为了扩展系统,提高读取性能。
下面通过几张图对ZAB的消息广播过程进行简单的介绍。
Zookeeper的消息广播过程类似 2PC(Two Phase Commit),ZAB仅需要超过一半以上的Follower返回 Ack 信息就可以执行提交,大大减小了同步阻塞,提高了可用性。
在Zookeeper集群启动、运行过程中,如果Leader出现崩溃、网络断开、服务停止或重启等异常情况,或集群中有新服务器加入时,ZAB会让当前集群快速进入崩溃恢复模式并选举出新的Leader节点,在此期间整个集群不对外提供任何读取服务。当产生了新的Leader后并集群中过半Follower完成了与Leader的状态同步,那么ZAB协议就会让Zookeeper集群从崩溃恢复模式转换成消息广播模式。崩溃恢复的目的就是保证当前Zookeeper集群快速选举出一个新的Leader并完成与其他Follower的状态同步,以便尽快进入消息广播模式对外提供服务。
Zookeeper崩溃恢复的主要任务就是选举Leader(Leader Election),Leader选举分两个场景:一个是Zookeeper服务器启动时Leader选举,另一个是Zookeeper集群运行过程中Leader崩溃后的Leader选举。在详细介绍Leader选举过程之前,需要先介绍几个参数:
另外在选举的过程中,每个节点的当前状态会在以下几种状态之中进行转变。
假设现在存在一个由5个Zookeeper服务器组成的集群Sever1,Sever2,Sever3,Sever4和Sever5,集群的myid分别为:1, 2,3,4,5。依次按照myid递增的顺序进行启动。由于刚启动时zxid和epoch都为0,因此Leader选举的关键因素成了myid。
在Zookeeper集群刚启动的时候,zxid和epoch并不参与群首选举。但是如果Zookeeper集群在运行了一段时间之后崩溃了,那么epoch和zxid在Leader选举中的重要性将大于myid。重要慎睁物性的排序为:epoch zxid myid。当某一个Follower与Leader失去通信的时候,就会进入Leader选举,此时Follower会跟集群中的其他节点进行通信,但此时会存在两种情况:
这种崩溃后的Leader选举机制也很好理解,如果Leader挂了,优先选择集群中最后做过(epoch)Leader的节点为新的Leader节点,其次选取有最新事务提交的节点(zxid)为Leader,最后才按默认的最大机器编号(myid)进行投票。
关于zookeeper最新和zookeeper370的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。