Raft一致性算法(11)


广播时间和平均故障间隔时间是由系统决定的,但是选举超时时间是我们自己选择的 。Raft 的 RPCs 需要接收方将信息持久化的保存到稳定存储中去,所以广播时间大约是 0.5 毫秒到 20 毫秒,取决于存储的技术 。因此,选举超时时间可能需要在 10 毫秒到 500 毫秒之间 。大多数的服务器的平均故障间隔时间都在几个月甚至更长,很容易满足时间的需求 。
6 集群成员变化
到目前为止,我们都假设集群的配置(加入到一致性算法的服务器集合)是固定不变的 。但是在实践中,偶尔是会改变集群的配置的,例如替换那些宕机的机器或者改变复制级别 。尽管可以通过暂停整个集群,更新所有配置,然后重启整个集群的方式来实现,但是在更改的时候集群会不可用 。另外,如果存在手工操作步骤,那么就会有操作失误的风险 。为了避免这样的问题,我们决定自动化配置改变并且将其纳入到 Raft 一致性算法中来 。
为了让配置修改机制能够安全,那么在转换的过程中不能够存在任何时间点使得两个领导人在同一个任期里同时被选举成功 。不幸的是,任何服务器直接从旧的配置直接转换到新的配置的方案都是不安全的 。一次性原子地转换所有服务器是不可能的,所以在转换期间整个集群存在划分成两个独立的大多数群体的可能性(见图 10) 。

Raft一致性算法

文章插图
 
 
图 10:直接从一种配置转到新的配置是十分不安全的,因为各个机器可能在任何的时候进行转换 。在这个例子中,集群配额从 3 台机器变成了 5 台 。不幸的是,存在这样的一个时间点,两个不同的领导人在同一个任期里都可以被选举成功 。一个是通过旧的配置,一个通过新的配置 。
 
为了保证安全性,配置更改必须使用两阶段方法 。目前有很多种两阶段的实现 。例如,有些系统在第一阶段停掉旧的配置所以集群就不能处理客户端请求;然后在第二阶段在启用新的配置 。在 Raft 中,集群先切换到一个过渡的配置,我们称之为共同一致(joint consensus);一旦共同一致已经被提交了,那么系统就切换到新的配置上 。共同一致是老配置和新配置的结合:
 
  • 日志条目被复制给集群中新、老配置的所有服务器 。
  • 新、旧配置的服务器都可以成为领导人 。
  • 达成一致(针对选举和提交)需要分别在两种配置上获得大多数的支持 。
 
共同一致允许独立的服务器在不影响安全性的前提下,在不同的时间进行配置转换过程 。此外,共同一致可以让集群在配置转换的过程中依然响应客户端的请求 。
集群配置在复制日志中以特殊的日志条目来存储和通信;图 11 展示了配置转换的过程 。当一个领导人接收到一个改变配置从 C-old 到 C-new 的请求,他会为了共同一致存储配置(图中的 C-old,new),以前面描述的日志条目和副本的形式 。一旦一个服务器将新的配置日志条目增加到它的日志中,他就会用这个配置来做出未来所有的决定(服务器总是使用最新的配置,无论他是否已经被提交) 。这意味着领导人要使用 C-old,new 的规则来决定日志条目 C-old,new 什么时候需要被提交 。如果领导人崩溃了,被选出来的新领导人可能是使用 C-old 配置也可能是 C-old,new 配置,这取决于赢得选举的候选人是否已经接收到了 C-old,new 配置 。在任何情况下,C-new 配置在这一时期都不会单方面的做出决定 。
一旦 C-old,new 被提交,那么无论是 C-old 还是 C-new,如果不经过另一个配置的允许都不能单独做出决定,并且领导人完全特性保证了只有拥有 C-old,new 日志条目的服务器才有可能被选举为领导人 。这个时候,领导人创建一条关于 C-new 配置的日志条目并复制给集群就是安全的了 。再者,每个服务器在见到新的配置的时候就会立即生效 。当新的配置在 C-new 的规则下被提交,旧的配置就变得无关紧要,同时不使用新的配置的服务器就可以被关闭了 。如图 11,C-old 和 C-new 没有任何机会同时做出单方面的决定;这保证了安全性 。
Raft一致性算法

文章插图
 
 
图 11:一个配置切换的时间线 。虚线表示已经被创建但是还没有被提交的配置日志条目,实线表示最后被提交的配置日志条目 。领导人首先创建了 C-old,new 的配置条目在自己的日志中,并提交到 C-old,new 中(C-old 的大多数和 C-new 的大多数) 。然后他创建 C-new 条目并提交到 C-new 中的大多数 。这样就不存在 C-new 和 C-old 可以同时做出决定的时间点 。


推荐阅读