ZooKeeper服务-一致性、实现


实现

ZooKeeper服务有两种不同的运行模式。一种是“独立模式”(standalone mode),即只有一个ZooKeeper服务器。这种模式比较简单,适合于测试环境,但是不能保证高可用性和可恢复性。在生产环境中的ZooKeeper通常以“复制模式”(replicated mode)运行于一个计算机集群上,这个计算及集群被称为一个“集合体”(ensemble)。
ZooKeeper通过复制来实现高可用性,只要集合体中半数以上的机器处于可用状态,它就能够提供服务。所以,一个集合体中通常包含奇数台机器。
ZooKeeper所做的就是确保对znode树的每一个修改都会被复制到集合体中超过半数的机器上。如果少于半数的机器出现故障,则最少有一台机器会保存最新的状态,其余的副本最终也会更新到这个状态。
ZooKeeper使用了Zab协议,该协议包括两个可以无限重复的阶段。
1. 阶段1:领导者选举
集合体中的所有机器通过一个选择过程来选出一台被称为“领导者“(leader)的机器,其他的机器被称为跟随者(follower)。一旦半数以上(或指定数量)的跟随者已经将其状态与领导者同步,则表明这个阶段已经完成。
2. 阶段2:原子广播
所有的写请求都会被转发给领导者,再由领导者将更新广播给跟随者。当半数以上的跟随者已经将修改持久化之后,领导者才会提交这个更新,然后客户端才会收到一个更新成功的相应。这个用来达成共识的协议被设计成具有原子性,因此每个修改要么成功要么失败。

如果领导者出现故障,其余的机器会选出另外一个领导者,并和新的领导者一起继续提供服务。随后,如果之前的领导者恢复正常,会成为一个跟随者。领导者选举的过程非常快,只需要大约200毫秒,因此在领导者选举的过程中不会出现系统性能的明显降低。
在更新内存中的znode树之前,集合体中的所有机器都会先将更新写入磁盘。任何一台机器都可以为读请求提供服务,并且由于读请求只涉及内存检索,因此非常快。


一致性

一个跟随者可能滞后于领导者几个更新。一个修改被提交之前,只需要集合体中半数以上机器已经将该修改持久化即可。对ZooKeeper来说,理想的情况就是将客户端都连接到与领导者状态一致的服务器上。每个客户端都有可能被连接到领导者,但客户端对此无法控制,甚至它自己都无法知道是否连接到领导者。
每一个对znode树的更新都被赋予一个全局唯一的ID,称为zxid(代表“ZooKeeper Transaction ID“). ZooKeeper要求对所有的更新进行编号并排序,它决定了分布式系统的执行顺序,如果zxid z1小于z2,则z1一定发生在z2之前。

以下几点保证了数据的一致性
1. 顺序一致性
来自任意特定客户单的更新都会按其发送顺序被提交。也就是说,如果一个客户端将znode z的值更新为a,在之后的操作中,它又将z的值更新为b,则没有客户端能够在看到z的值是b之后再看到值a(如果没有其他对z的更新)
2. 原子性
每个更新要么成功,要么失败。这意味着如果一个更新失败,则不会有客户端看到这个更新的结果。
3. 单一系统映像
一个客户端无论连接到哪一台服务器,它看到的都是同样的系统视图。这意味着,如果一个客户端在同一个会话中连接到一台新的服务器,它所看到的系统状态不会比在之前服务器上所看到的更老。当一台服务器出现故障,导致它的一个客户端需要尝试连接集合体中其它的服务器时,所有状态滞后于故障服务器的服务器都不会接受该连接请求,除非这些服务器将状态更新至故障服务器的水平。
4. 持久性
一个更新一旦成功,其结果就会持久存在并且不会被撤销。这表明更新不会受到服务器故障的影响。
5. 及时性
任何客户端所看到的滞后系统视图都是有限的,不会超过几十秒。这意味着与其允许一个客户端看到非常陈旧的数据,还不如将服务器关闭,强迫该客户端连接到一个状态较新的服务器。
出于性能的原因,所有的读操作都是从ZooKeeper服务器的内存获得数据,它们不参与写操作的全局排序。如果客户端之间通过ZooKeeper之外的机制进行通信,则客户端可能会发现它们所看到的ZooKeeper状态是不一致的。
例如,客户端A将znode z的值从a更新为a1,接着A告诉B去读z的值,而B读到的值是a而不是a1。这与ZooKeeper的一致性保证是完全兼容的(这种情况称为“跨客户端视图的同时一致性“)。为了避免这种情况发生,B应该在读z的值之前对z调用sync操作。Sync操作会强制B所连接的ZooKeeper服务器”赶上“领导者,这样当B读z的值时,所独到的将会是A所更新的。
Sync操作只能以异步的方式被调用。不需要等待sync调用的返回,ZooKeeper会保证任何后续的操作都在服务器的sync操作完成后才执行,哪怕这些操作是在sync操作完成之前发出的。

原文地址:https://www.cnblogs.com/EnzoDin/p/10091763.html