最终一致性数据库:现状
引言
最终一致性 [1] 是一种一致性模型,被许多大型分布式数据库采用。这类数据库要求对副本数据的所有更改最终都能到达所有受影响的副本。此外,这些数据库不处理冲突解决,当发生冲突更新时,责任被推给应用程序开发者。最终一致性是一种特定形式的弱一致性:存储系统保证如果对象没有新的更新,最终所有访问都会返回最后更新的值 [1]。如果未发生故障,不一致窗口的最大大小可以根据通信延迟、系统负载以及复制方案中涉及的副本数量等因素确定。我们之前在 https://blog.mariadb.org/mariadb-eventually-consistent/ 研究了 MariaDB 是否最终一致,结果发现在大多数配置下,它可以是。
定义:最终一致性。
- 最终交付:在一个节点上执行的更新最终会在所有节点上执行。
- 终止:所有更新执行都会终止。
- 收敛:执行了相同更新的节点最终会达到等效状态(并保持不变)。
示例:考虑一个情况,所有三个节点上的数据项 R=0。假设我们在节点 0 上有以下写入和提交序列:W(R=3) C W(R=5) C W(R=7) C。现在在节点 1 上的读取可能返回 R=5,从节点 2 的读取可能返回 R=7。只要最终从所有节点的读取都返回相同的值,这就是最终一致的。请注意,这个最终值可能是 R=5。最终一致性不限制写入必须执行的顺序。
在本博客中,我们将简要介绍使用最终一致性的数据库管理系统,并根据流行度、成熟度、一致性和用例来评估回顾的数据库。在此基础上,我们提出了最终一致性的优点和缺点。这项研究的一个更长、更全面的版本已发表在 [13] 上。
使用最终一致性的数据库
MongoDB [2] 是一个跨平台的面向文档的 NoSQL 数据库系统,使用 BSON 作为数据模型来存储数据。MongoDB 是免费的开源软件,并为各种流行的编程语言和开发环境提供官方驱动程序。Web 编程语言 Opa 也内置支持 MongoDB,并在 MongoDB 之上提供类型安全层。还有大量针对其他编程语言和框架的非官方或社区支持的驱动程序。
CouchDB [3] 是一个开源的 NoSQL 数据库,使用 JSON 作为其数据模型,JavaScript 作为其查询语言,HTTP 作为 API。CouchDB 最初于 2005 年发布,后来于 2008 年成为 Apache 项目。CouchDB 的突出特点之一是多主复制。
Amazon SimpleDB [4] 是一个由 Amazon.com 使用 Erlang 编写的分布式数据库。它与 Amazon Elastic Compute Cloud (EC2) 和 Amazon S3 一起作为网络服务使用,是 Amazon Web Services 的一部分。它于 2007 年 12 月 13 日宣布。
Amazon DynamoDB [5,6] 是由 Amazon.com 作为 Amazon Web Services 组合一部分提供的完全托管的专有 NoSQL 数据库服务。DynamoDB 使用与 Dynamo 类似的数据模型,其名称也源于 Dynamo,但底层实现不同:DynamoDB 采用单主设计。DynamoDB 由亚马逊 CTO Werner Vogels 于 2012 年 1 月 18 日宣布。
Riak [7] 是一个开源、容错的键值 NoSQL 数据库,它实现了 Amazon Dynamo 的原理。Riak 使用一致性哈希来在节点间分布数据,并使用桶来存储数据。
DeeDS [8] 是一个分布式、主动实时数据库系统的原型。它旨在为实时应用程序提供数据存储,这些应用程序可能具有硬性或软性实时要求。作为数据库,DeeDS 使用 OBST (Object Management system of STONE) 和 TDBM (带事务的 DBM),后者取代了 OBST 存储管理器。引入 TDBM 的一个主要原因是在 DeeDS 中添加嵌套事务的支持。TDBM 是一个具有分层架构的事务处理数据存储,并为 DeeDS 提供
- 嵌套事务
- 易失性和持久性数据库
- 支持超大数据项
ZATARA 数据库 [9] 是一个分布式数据库引擎,其特点是抽象查询接口和可插拔的内部数据结构。ZATARA 设计用于灵活地被任何软件应用程序使用,并保证数据完整性,同时实现高性能和可伸缩性。
DeeDS 和 ZATARA 都是研究项目的结果,尚未成熟到可用于生产环境。
我们使用以下标准来评估支持最终一致性的数据库系统
- 流行度
- 成熟度
- 一致性
- 用例
流行度
我们根据 DB Engines 排名 (http://db-engines.com/en/ranking) 评估了所介绍数据库系统的流行度。DB Engines 排名根据数据库管理系统的流行度对其进行排名。2014 年初,MongoDB 排名第 7 位,得分为 96.1。2014 年 6 月,它排名第 5 位,得分为 231.44。2014 年初,CouchDB 排名第 16 位。2014 年 6 月,CouchDB 排名第 21 位,得分为 22.78。2014 年初,Riak 排名第 27 位。2014 年 6 月,Riak 排名第 30 位,得分为 10.82。2014 年初,DynamoDB 排名第 35 位,得分为 7.20。2014 年 6 月,DynamoDB 排名第 32 位,得分为 9.58。2014 年初,SimpleDB 排名第 46 位。2014 年 6 月,SimpleDB 排名第 52 位,得分为 2.94。
根据此排名,MongoDB 显然是支持最终一致性最流行和最广为人知的数据库系统。作为参考,MySQL 在 2014 年 6 月排名第 2 位,MariaDB 排名第 28 位。
成熟度
基于作者的研究,MongoDB 显然是使用最终一致性最成熟的数据库系统。它拥有庞大的用户群和客户基础,并且正在积极开发。MongoDB 为多种流行的编程语言和开发环境提供官方驱动程序。还有大量的非官方或社区支持的驱动程序,适用于其他编程语言和框架。
Riak 在 Apache 2 许可下免费提供。此外,Riak 通过 Basho Technologies 提供商业许可,包括订阅支持和多数据中心 (MDC) 复制功能。Riak 提供 Ruby、Java、Erlang、Python、PHP 和 C/C++ 的官方驱动程序。还有许多社区支持的驱动程序,适用于其他编程语言和框架。
CouchDB 是一个 NoSQL 数据库。CouchDB 使用 JSON 存储数据,支持 JavaScript 和 Erlang 中的 MapReduce 查询函数。CouchDB 最初于 2005 年发布,并于 2008 年成为 Apache 项目。CouchDB 的复制和同步功能使其非常适合移动设备,在这些设备上网络连接无法保证,但应用程序必须离线继续工作。CouchDB 也适用于数据不断累积、偶尔更改、需要运行预定义查询以及版本控制很重要的应用程序(例如 CRM、CMS 系统)。主主复制是 CouchDB 的一个特别有趣的特性,它允许轻松进行多站点部署。CouchDB 显然是一个成熟的系统,已用于生产环境。
DynamoDB 是一项由 Amazon.com 作为 Amazon Web Services 组合一部分提供的商业托管 NoSQL 数据库服务。DynamoDB 还有一个本地开发版本,开发者可以使用它在本地测试支持 DynamoDB 的应用程序。支持 DynamoDB 绑定的编程语言包括 Java、Node.js、.NET、Perl、PHP、Python、Ruby 和 Erlang。因此,DynamoDB 是一项成熟且具备生产质量的服务。
Amazon SimpleDB 处于 Beta 阶段,因此我们不建议在生产环境中使用它。ZATARA 和 DeeDS 处于研究阶段,没有公开可用的系统进行测试。因此,它们最多处于 Alpha 阶段,我们也不建议在生产环境中使用它们。
一致性
从之前的研究可知,Amazon SimpleDB 对于最终一致性读取的不一致窗口几乎总是小于 500 毫秒 [10],而另一项研究发现 Amazon S3 的不一致窗口持续长达 12 秒 [10]。然而,据作者所知,目前还没有一个广为人知且被接受的、用于使用最终一致性数据库的工作负载。因此,一致性或不一致性的比较必须完全基于系统特性。从一致性的角度来看,Riak 提供了最可配置的一致性特性,允许选择一致性级别。
MongoDB、SimpleDB 和 DynamoDB 提供了读取最新版本数据项的可能性,从而提供了强一致性以及最终一致性。其他所有回顾的系统都只提供最终一致性,并在执行读操作时可能返回旧版本的数据。
用例
MongoDB 已成功应用于运营智能,尤其是在存储日志数据、创建预聚合报告和分层聚合方面。此外,MongoDB 还用于产品管理系统,存储产品目录、管理库存和类别层级。在内容管理系统中,MongoDB 用于存储元数据、资产管理以及存储用户对内容的评论,例如博客文章和媒体。
Riak 已成功应用于简单的读写密集型应用程序,例如会话存储、广告投放、日志数据和传感器数据存储。此外,Riak 还用于内容管理和社交应用程序,存储用户账户、用户设置和偏好、用户事件和时间线以及文章和博客文章。
CouchDB 的复制和同步功能非常适合移动环境,在这些环境下网络连接无法保证,但应用程序必须离线继续工作。CouchDB 也非常适合数据不断累积、偶尔更改、需要运行预定义查询以及版本控制很重要的应用程序。CRM、CMS 系统就是这类应用程序的例子。CouchDB 有一个特别有趣的特性:主主复制,它允许轻松进行多站点部署。
SimpleDB 非常适合日志记录、在线游戏和元数据索引。然而,SimpleDB 不能用于聚合报告:SimpleDB 中没有 SUM、AVERAGE、MIN 等聚合函数。元数据索引是 SimpleDB 的一个非常好的用例。您还可以将数据存储在 S3 中,并使用 SimpleDB 域来存储指向 S3 对象的指针,并附加更多关于这些对象的信息。SimpleDB 适用于的另一类应用程序是应用程序中独立组件之间共享信息。SimpleDB 还提供了一种共享索引信息(即可搜索信息)的方式。SimpleDB 项的大小有限,但可以使用 S3 存储更大的对象,如图片和视频,并在 SimpleDB 中指向它们。这可以称为元数据索引。
优点和缺点
优点
最终一致性易于实现,并为客户端提供一定程度的一致性 [11]。构建最终一致性数据库相对于构建强一致性数据库有两个优点:(1)构建具有较弱保证的系统要容易得多,以及(2)通过网络分区与较大数据库集群分离的数据库服务器仍然可以接受来自应用程序的写入。毫不意外,后一个理由是第一代采用最终一致性的 NoSQL 系统创建者给出的。
最终一致性通常也是强一致性的。最近的几个项目验证了现实世界中最终一致性存储的一致性 [10]。
缺点
尽管最终一致性易于实现,但目前的定义并不精确 [11]。首先,从目前的定义来看,最终一致性数据库的状态并不清楚。一个总是返回值 42 的数据库是最终一致的,即使从未写入过 42。一个可能的定义是,最终所有访问都会返回最后更新的值,因此数据库不能收敛到任意值 [1]。即使是这个新定义也有另一个问题:在达到最终状态之前,可以返回什么值?如果副本尚未收敛,可以对返回的数据做出什么保证?在这种情况下,唯一的可能解决方案是返回最后已知的、一致的值。这里的问题是如何知道数据项的哪个版本在所有副本上已收敛到相同状态 [1]。
最终一致性要求对一个副本的写入最终会出现在其他副本上,并且如果所有副本都收到了相同的写入集,它们将对所有数据拥有相同的值。这种弱一致性形式不以任何方式限制不同键操作的顺序,从而迫使程序员考虑所有可能的顺序,并向用户暴露许多不一致性。例如,在最终一致性下,Alice 更新她的个人资料后,刷新页面后可能看不到该更新。或者,如果 Alice 和 Bob 在博客文章上互相评论,Carol 可能看到对话中随机的非连续子集。当工程师在最终一致性数据库上构建应用程序时,每次从数据库访问数据时,都需要回答几个棘手的问题
- 如果数据库读取返回任意旧值,对应用程序有什么影响?
- 如果数据库看到修改以错误的顺序发生,对应用程序有什么影响?
- 如果一个客户端正在修改数据库,而另一个客户端试图读取它,对应用程序有什么影响?
- 我的数据库更新对正在尝试读取数据的其他客户端有什么影响?
这是一份难题列表,开发人员必须努力工作才能回答这些问题。本质上,工程师需要手动进行工作,以确保多个客户端不会在节点之间引入不一致。
至少部分解决这些问题的一种方法是使用更强的最终一致性版本。
定义:强最终一致性。
- 最终交付:在一个节点上执行的更新最终会在所有节点上执行。
- 终止:所有更新执行都会终止。
- 强收敛:执行了相同更新的节点具有等效状态。
据作者所知,目前还没有数据库系统使用强最终一致性。这可能是因为它更难实现。最终一致性明显削弱了传统数据库提供的保证,并对软件开发人员提出了要求。设计即使数据库的准确性无法完全依赖也能保持正确行为的应用程序是很困难的。
事实上,Google 在其关于 F1 数据库的最新论文 [12] 中解决了最终一致性的痛点,并指出:“我们在 Google 也积累了大量关于最终一致性系统的经验。在所有这类系统中,我们发现开发者会花费相当大一部分时间构建极其复杂且容易出错的机制来应对最终一致性并处理可能过时的数据。我们认为这给开发者带来了不可接受的负担,并且一致性问题应该在数据库层面解决。”
结论
显然,目前有几个非常成熟且流行的数据库系统使用最终一致性。其中大多数都在积极开发中,并拥有强大的社区支持。我们相信将来会看到更多使用最终一致性或强最终一致性的数据库系统。
参考文献
[1] Vogels, W.:可伸缩 Web 服务:最终一致性,《ACM Queue》,第 6 卷,第 6 期,第 14-16 页,2009 年 10 月。
[2] MongoDB:敏捷且可伸缩。http://www.mongodb.org/
[3] Anderson, C. J.、Lehnardt, J. 和 Slater, N.:CouchDB:权威指南。由 O’Reilly Media, Inc. 出版,地址:1005 Gravenstein Highway North, Sebastopol, CA 95472。2010 年 1 月,第一版。
[4] Amazon SimpleDB,http://aws.amazon.com/simpledb/
[5] DynamoDB,http://aws.amazon.com/dynamodb/
[6] Sivasubramanian, S.:Amazon DynamoDB:一个无缝可伸缩的非关系型数据库服务。收录于 SIGMOD 国际数据管理大会论文集,ACM 纽约,纽约州,美国,2012 年,第 729-730 页。
[7] Riak,http://basho.com/riak/
[8] F. Andler, J. Hansson, J. Mellin, J. Eriksson 和 B. Eftring:DeeDS 实时数据库架构概述。收录于 1998 年第六届并行与分布式实时系统国际研讨会论文集。
[9] Bogdan Carstoiu 和 Dorin Carstoiu:Zatara,可插拔的最终一致性分布式数据库。《AISS》,2(3),2010 年。
[10] Bermbach, D. 和 Tai S:最终一致性:最终有多快?第六届面向服务计算中间件研讨会论文集,第 1-5 页,2011 年。
[11] Bailis, P. 和 Ghodsi, A:当今的最终一致性:局限、扩展及其他。《ACM 通讯》,第 56 卷,第 5 期,第 55-63 页,2013 年 5 月。
[12] Shute Jeff, Vingralek Radek, Samwel Bart, Handhy Ben, Whipkey Chad, Rollins Eric, Oancea Mircea, Littlefield Kyle, Menestina David, Ellner Stephqan, Cieslewicz John, Rae Ian, Stancescu Traian, Apte Himani:F1:一个可伸缩的分布式 SQL 数据库,《VLDB》,2013 年。
[13] Mawahib Musa Elbushra, Jan Lindström:最终一致性数据库:现状,《OJDB 2014》,1(1),第 26-41 页,2014 年,https://www.ronpub.com/journals/ojdb/2014-vol1/issue1/OJDB-v1i1n03_Elbushra.pdf。