在分布式系统中,为了高可用和容错性,数据需要被复制到多个服务器上。为了保证数据在多个服务器上最终一致,需要一种机制保证一个operation只有在一定数目的服务器上完成后,服务器才回复这个operation的成功,我们称这个过程为这些服务器达成了Quorum, 有点类似于投票。
写的Quorum如果小于服务器的数量的话,客户端可能读到不一致的数据。举个例子,a=5存储在服务器s1, s2, s3上,现在我们要写a=7,那么我们可以选2个服务器这样大多数的服务器会得到最新的a=7的数值,然后我们返回写的成功。如果s1和s2得到a=7然后客户端c1的读在a=7还没有发到s3上时读了s3,这样我们就会返回a=5. 如何选择Quorum才能保证读写的一致呢?假设我们有N个node,至少超过一半的node在线才能保证一致性。如果有5个node,至少需要3个在线;如果有4个node,也至少需要3个在线。因为5个node可以有2个fail而4个只能用有1个fail,一般选奇数个node的服务器群。
Quorum是这样都到的:R + W > N;R是最少需要读的node,W是最少需要写的node,N是总数。例如:
(N=3, W=2, R=2): 写必须2个node返回成功写操作才能返回成功;读需要2个node成功返回。
(N=3, W=1, R=3): 写只需要1个node返回成功写操作就能返回成功;读需要3个都读。写很快,都很慢,如果写完一个node在备份到其他两个node之前这个node fail,那么写的数据将被丢失,所以不是很durable。
(N=3, W=3, R=1): 写需要三个都成功;读只需要一个,durable。如果有node有问题,写操作会失败,所以可用性不高。
一般情况下大部分系统写操作比读操作少很多,所以一般需要快读而牺牲一些写的速度,1 < R < W < N。常见的quorum algorithm有Paxos,几乎所有的大型分布式系统需要严格的quorum的都有用,之后深入学习后会分享。有趣的是亚马逊早期的dynamo (和AWS的DynamoDB不同)用的是Sloppy Quorum, 所以的读写操作都是在前N个健康的node上的,每次不一定是同N个node。