最近在读 acmqueue 中近十年的历史文章,因此接下来应该会有不少与之相关的阅读笔记。
今天这篇笔记是讨论数据一致性概念的文章,作者是大名鼎鼎的All Things Distributed博客博主,AWS的CTO Werner Vogels。文章完成于2008年,但是其核心观念和论证至今依然有效。
言归正传,跟着 Werner Vogels 的思路开始讨论数据一致性这个问题吧。
在分布式系统领域里,有一个著名的CAP理论。CAP理论认为数据一致性(C)、系统可用性(A)和网络分区容忍性(P),在系统中的任何时刻三个性质中只能同时保证两个性质成立;而网络常常又是不可靠的。
因此简单来说:在数据一致性和系统可用性中,开发者如果选择数据一致性,例如当系统发生写入操作时,在数据没有确认写入所有副本之前,系统就需要面对可能不可用的现实;当开发者强调系统可用性时,系统可以一直接受写操作的请求,但是极端条件下,读操作有可能无法返回最新写入的数据。
因此如何在系统可用性和数据一致性之间找到一个平衡点,在历史上就成了一个非常有趣的话题。
注意这里提到的数据一致性要和数据库里的 ACID 性质进行区分。数据库中的一致性(C)是指一个事务完成后数据库是处于一种一致状态。最常见的就是转账,从一个账户转移到一个新的账户,两个账户的总额应该不变的。这里的一致性是由开发者保证的,数据库仅仅是保证完整性约束。而下文提到的一致性不同,更像是“多个数据副本看起来好像只有一个副本,且其所有操作都是原子性的”。
文中还提到了在九十年代互联网尚未兴起时,开发者大多选择牺牲可用性来保证系统的一致性;而后互联网兴起时,软件产品开始面对消费者,可用性逐渐重要起来了。这个时候开发者开始考虑如何牺牲一定的一致性来保证可用性。
作者从客户端和服务端(Client and Server)角度来叙述数据一致性的概念。
对于客户端而言,数据一致性可以分为下面三种类型:
当然,最终一致性还有许多变种,例如:
对于服务端的一致性,作者只提到了 Dynamo 风格的 quorum 算法的最终一致性实现方式,即 R+W>N 。
N = 存储数据副本的节点的数量 W = 更新成功所需的副本更新成功的数量 R = 一次数据对象读取要访问的副本的数量
除了 Dynamo 风格外,随着分布式系统实践的深入,各种新的共识算法(Raft等)也能提供强一致性,对应的工程实践就有 zookeeper 和 etcd 等等。
总的来说,Werner Vogels的这篇文章恰当的总结了数据一致性的概念,放在2008年那个时间段是相当有力的。