原文
https://martinfowler.com/articles/patterns-of-distributed-systems/quorum.html
每个决策都需要大多数服务器同意,避免两组服务器各自独立做出决策。
2020.8.11
在一个分布式系统中,无论服务器采取任何的行动,都要确保即便在发生崩溃的情况下,行动的结果都能够对客户端可用。要做到这一点,可以将结果复制到其它的服务器上。但是,这就引出了一个问题:需要有多少服务器确认了这次复制之后,原来的服务器才能确信这次更新已经完全识别。如果原来的服务器要等待过多的复制,它的响应速度就会降低——也就减少了活跃度。但如果没有足够的复制,更新可能会丢失掉——安全性失效。在整体系统性能和系统连续性之间取得平衡,这一点至关重要。
集群收到一次更新,在集群中的大多数节点确认了这次更新之后,集群才算是确认了这次更新。我们将这个数量称之为 Quorum。因此,如果我们的集群有 5 个节点,我们需要让 Quorum 为 3(对于 n 个节点的集群而言,quorum 是 n/2 + 1)。
Quorum 的需求表示,可以容忍多少的失效——这就是集群规模减去 Quorum。5 个节点的集群能够容忍其中的 2 个节点失效。总的来说,如果我们想容忍 “f” 个失效,集群的规模应该是 2f + 1。
考虑下面两个需要 Quorum 的例子:
- 更新服务器集群中的数据。高水位标记(High-Water Mark)保证了一点,只有大多数服务器上确保可用的数据才是对客户端可见的。
- 领导者选举。在领导者和追随者(Leader and Followers)模式中,领导者只有得到大多数服务器投票才会当选。
只有在大部分服务器都在运行时,集群才能发挥其作用。进行数据复制的系统中,有两点需要考虑:
-
写操作的吞吐
每次数据写入集群时,都需要复制到多台服务器上。每新增一台服务器都会增加完成这次写入的开销。数据写的延迟直接正比于形成 Quorum 的服务器数量。正如我们将在下面看到的,如果集群中的服务器数量翻倍,吞吐值将会降低到原有集群的一半。
-
能够容忍的失效数量
能容忍的失效服务器数量取决于集群的规模。但是,向既有集群增加一台服务器并非总能得到更多的容错率:在一个有三台服务器的集群中,增加一台服务器,并不会增加失效容忍度。
考虑到这两个因素,大多数实用的基于 Quorum 的系统集群规模通常是三台或五台。五台服务器集群能够容忍两台服务器失效,其可容忍数据写入的吞吐是每秒几千个请求。
下面是一个选择服务器数量的例子,根据可容忍的失效数量,以及在吞吐上近似的影响。吞吐一列展示了近似的相对吞吐量,这样就凸显出吞吐量随着服务器数量的增加而降低。这个数字会因系统而异。作为一个例子,读者可以参考在 Raft 论文和原始的 Zookeeper 论文中公布的实际的吞吐数据。
服务器的数量 | Quorum | 可容忍的失效数量 | 表现的吞吐量 |
---|---|---|---|
1 | 1 | 0 | 100 |
2 | 2 | 0 | 85 |
3 | 2 | 1 | 82 |
4 | 3 | 1 | 57 |
5 | 3 | 2 | 48 |
6 | 4 | 2 | 41 |
7 | 5 | 3 | 36 |