Apache > ZooKeeper
 

Oracle Quorum 简介

Oracle Quorum简介通过引入一种称为Oracle的故障检测器,提高了由2个ZooKeeper实例组成的集群的可用性。Oracle的设计目的是在双实例配置中,当另一个实例被故障检测器Oracle判定为故障时,向唯一存活的实例授予权限。

Oracle的实现

每个实例都应访问一个包含0或1的文件,以指示该实例是否已获得Oracle的授权。然而,由于故障检测算法各不相同,这一设计可以更改。因此,开发者可以重写QuorumOracleMaj中的askOracle()方法,以适应首选的Oracle消息解密方式。

部署上下文

Oracle的设计目的是提高由2个ZooKeeper实例组成的集群的可用性;因此,投票成员的数量为2。换句话说,Oracle解决了在两实例集群中可能出现故障实例的共识问题。

当投票成员数量超过2时,确保Oracle正常工作的预期方式是在识别出故障机器时重新配置集群规模。例如,在5个实例的配置下,当故障机器与Leader断开连接时,预期会向集群发送reconfig客户端请求,使集群重新配置为4个实例。因此,一旦投票成员数量等于2,该配置就会进入Oracle设计要解决的问题领域。

如何在zoo.cfg中部署Oracle

无论集群规模大小,oraclePath 必须像其他静态参数一样在初始化时配置。以下展示了正确指定并启用 Oracle 的方法。

oraclePath=/to/some/file

zoo.cfg 配置示例:

dataDir=/data
dataLogDir=/datalog
tickTime=2000
initLimit=5
syncLimit=2
autopurge.snapRetainCount=3
autopurge.purgeInterval=0
maxClientCnxns=60
standaloneEnabled=true
admin.enableServer=true
oraclePath=/chassis/mastership
server.1=0.0.0.0:2888:3888;2181
server.2=hw1:2888:3888;2181

QuorumOracleMaj 旨在读取故障检测器的结果,该结果被写入一个文本文件,即oracle文件。
zoo.cfg中的配置如下所示:

oraclePath=/to/some/file

假设您已将故障检测器的结果写入/some/path/result.txt,那么正确的配置如下:

oraclePath=/some/path/result.txt

那么,提供的文件中正确内容应该是什么?可以通过终端执行以下命令创建一个示例文件:

$echo 1 > /some/path/result.txt

任何等效文件都适用于当前QuorumOracleMaj的实现。Oracle文件的数量应等于为启用Oracle而配置的ZooKeeper实例数量。换句话说,每个ZooKeeper实例都应拥有自己的oracle文件,且这些文件不应共享;否则将会出现下一节所述的问题。

启用Oracle后部署的不同之处

QuorumPeerConfig读取到zoo.cfg包含oraclePath时,它将创建QuorumOracleMaj实例而非默认的QuorumVerifierQuorumMaj。QuorumOracleMaj继承自QuorumMaj,并通过重写containsQuorum()方法与父类区分。QuorumOracleMaj的设计目的是当Leader失去所有follower且无法维持法定人数时,执行其特有版本的containsQuorum。在其他情况下,QuorumOracleMaj将按照QuorumMaj的方式执行。

使用Oracle时需要注意的事项

我们考虑一个异步分布式系统,该系统由2个ZooKeeper实例和一个Oracle组成。

活跃性问题:

当我们考虑预言机满足由[CT]提出的以下属性时:

Strong Completeness: There is a time after which every process that crashes is permanently suspected by every correct processes

系统的活性由Oracle确保。然而,当引入的oracle无法维持该属性时,将如以下示例所示预期发生活性丢失。

假设我们有一个Leader和一个Follower,它们正在广播状态下运行,当出现以下情况时系统将失去活性:

  1. The Leader fails, but the Oracle does not detect the faulty Leader, which means the Oracle will not authorize the Follower to become a new Leader.
    1. 当Follower发生故障,但Oracle未检测到该故障Follower时,意味着Oracle将授权Leader推动系统继续运行。

安全问题:

进度丢失

当系统在不同时间发生多次故障时,进度可能会丢失,如下例所示,

假设我们有一个领导者(Ben)和一个跟随者(John)处于广播状态,

At T1 with zxid(0x1_1): L-Ben fails, and the F-John takes over the system under the authorization from the Oracle.
At T2 with zxid(0x2_1): The F-John becomes a new Leader, L-John, and starts a new epoch.
At T3 with zxid(0x2_A): L-John fails
At T4 with zxid(0x2_A): Ben recovers up and starts its leader election.
At T5 with zxid(0x3_1): Ben becomes the new leader, L-Ben, under the authorization from the Oracle.

在这种情况下,系统在L-Ben失败后丢失了进度。

然而,通过使Oracle能够引用最新的zxid,可以防止进度丢失。当Oracle能够引用最新的zxid时,

At T5 with zxid(0x2_A): Ben will not end his leader election because the Oracle would not authorize although John is down.

尽管如此,我们以牺牲活性为代价换取了安全性。

脑裂问题

我们认为Oracle满足[CT]提出的以下期望属性,

Accuracy: There is a time after which some correct processes is never suspected by any processes

然而,Oracle给出的决策应该是互斥的。

换句话说,

假设我们有一个领导者(Ben)和一个跟随者(John)处于广播状态,

当Oracle在领导者选举阶段无法维持这一属性时,预计会出现脑裂问题

  1. Start of the system
    1. 故障实例从故障中恢复。

故障检测器实现概念示例

需要考虑的是,故障检测器的输出结果是授权查询ZooKeeper实例,判断其是否有权在不等待故障实例的情况下推动系统前进,该故障实例由故障检测器识别。

硬件实现方案

假设有两台专用硬件设备hw1和hw2,分别可以托管ZooKeeper实例zk1和zk2,并组成一个集群。有一个硬件设备同时连接到这两台硬件上,能够判断硬件是否通电。因此,当hw1断电时,zk1无疑会出现故障。于是该硬件设备会将hw2上的oracle文件更新为1,这表示zk1已故障,并授权zk2推动系统继续运行。

软件实现

假设有两台专用硬件设备hw1和hw2,可以分别托管ZooKeeper实例zk1和zk2,并组成集群。我们可以在hw1和hw2上分别部署两个额外服务o1和o2。o1和o2的职责是检测另一台硬件是否存活。例如,o1可以持续ping hw2来判断hw2是否通电运行。当o1无法ping通hw2时,o1会判定hw2出现故障,随后将zk1的oracle文件更新为1,这个值表示zk2已故障,并授权zk1推动系统继续运行。

使用USB设备作为Oracle来维护进度

在macOS 10.15.7 (19H2)系统中,外部存储设备会挂载在/Volumes目录下。因此,我们可以插入包含所需信息的USB设备作为oracle。当设备连接时,oracle会授权领导者推动系统前进,这也意味着其他实例将失败。重现这个刺激需要六个步骤。

(注意) 由于本次模拟中仅存在单一USB设备,因此不会出现脑裂问题。 此外,mastership不应由多个实例共享。 因此,仅配置了一个与Oracle连接的ZooKeeper实例。 更多详情请参阅安全议题章节。

  1. 发生领导者故障,由于oracle的存在,剩余实例自行完成领导者选举。
  2. 由于oracle的存在,法定人数仍然得以维持。

通过这些步骤,我们可以轻松演示并实践oracle如何在双实例系统中运作。

参考文档

[CT] Tushar Deepak Chandra 和 Sam Toueg。1991年。《异步系统中的不可靠故障检测器(初步版本)》。发表于第十届ACM分布式计算原理年度研讨会论文集PODC '91)。美国纽约州纽约市计算机协会,325-340页。DOI:https://doi.org/10.1145/112600.112627