本文将从分布式数据库的角度,为您比较PostgreSQL、CockroachDB、MongoDB、Redis和ScyllaDB的共同点和不同之处。
译者 | 陈峻
审校 | 孙淑娟
在过去的十年间,分布式系统已遍布全球。它们跨区域地使用编排技术,实现了横跨多个云服务提供商及本地基础设施的混合云式部署,负载平衡,以及高可用性。在此基础上,数据库领域也在不断迭代与发展。近年来,业界大量涌现了专为分布式数据库部署而设计的新型数据库系统。当然,也有部分数据库已在原有的设计中,添加了分布式架构组件。
DB-Engines.com评出的百强数据库
知名网站DB-engines.com使用加权算法,跟踪了各种数据库在各个平台上的提及次数、Google的搜索趋势、Stack Overflow上的讨论频率、推文发布的职业技能次数、以及LinkedIn个人资料出现的数量。下图展示了截至2022年5月,在上榜的394种数据库中,市场占比前100的数据库分布情况。
截至2022年5月,DB-Engines.com上排名前100的数据库
其中,作为传统的SQL系统,关系数据库管理系统(RDBMS)仍占比最大,高达47%。而占比25%是NoSQL系统,涵盖了丰富的类型,包括:MongoDB之类的文档数据库、Redis之类的键值系统、ScyllaDB之类的宽列(wide column)数据库、以及Neo4j之类的图形数据库。而占比11%的“多模型”数据库包含了在同一系统中,同时支持SQL和NoSQL的混合体(如:Microsoft的Cosmos DB和ArangoDB),或支持多种NoSQL数据模型的数据库(如:DynamoDB,它将自己列为NoSQL键值系统和一个文件存储的集合)。
什么是分布式数据库?
人们对于如何构建符合SQL(源自ANSI/ISO/IEC9075:2016的正式标准化)的分布式RDBMS系统有着不同的理解。目前ANSI、ISO、IETF或W3C尚未对“NoSQL数据库”进行明确的定义。在我看来,分布式数据库的基本特征是:首先定义了一个集群,并在其中分布了不同的数据;接着,集群中定义了各个节点角色。每个节点或是对等节点,或是有某些节点处于领导位置,而其他节点扮演跟随者的角色。然后,这些角色能够实现彼此的故障转移。最后,它们能够尽可能地均匀复制和分片数据。
在此基础上,我们可以从上述名列前100名的数据库中,挑选出5种典型的,并将它们分为如下两类:
SQL+NewSQL | NoSQL |
PostgreSQL | MongoDB |
CockroachDB | Redis |
ScyllaDB(Cassandra) |
在上表的左侧,Postgres和CockroachDB代表了分布式SQL。其中,CockroachDB号称“NewSQL”,是专为分布式数据库而设计的。在上表的右侧,MongoDB、Redis和ScyllaDB都属于分布式NoSQL。总地说来,如果您需要表联合(JOIN)操作的话,可以沿用SQL和RDBMS。如果您需要对数据进行非规范化,那么便可以选择NoSQL。
多数据中心集群
前面提到了集群的概念。早在多数据中心的设计架构被提出之前,PostgreSQL、MongoDB和Redis都被设计为单数据中心的本地集群。
如上表所示,首发于1986年的Postgres,完全早于云计算的概念。但随着时间的推移,它在设计和功能上发生了不少的改进。
作为NewSQL的代表,CockroachDB在设计之初就考虑到了全局性分布。
MongoDB在公有云诞生之初发布,其最初的设计只考虑到了单个数据中心集群,现在也增加了对于各种不同拓扑的支持。使用MongoDB Atlas,您可以非常轻松地将其部署到多个区域中。
根据低延迟的设计理念,Redis通常被部署在单个数据中心中。同时,它也提供了允许部署多数据中心的企业功能。
ScyllaDB和Cassandra一样,从一开始就在设计中考虑了多数据中心的部署。
集群
在分布式数据库的概念中,我们提到了复制和分片。这完全取决于数据库架构的分层或同构程度。例如,MongoDB只有一个主节点,其余都是该主节点的副本(被称为副本集)。您只能在主节点上写入数据库。而由于副本为只读,因此您无法直接更新它们,而必须由主节点去更新其他副本。显然,这些节点是异构的,而不是同构的。
这类主备(Primary-Replica)架构有助于在重读取(read-heavy)的工作负载中分配流量。而在混合或重写入(write-heavy)的工作负载中,主节点会成为瓶颈。也就是说,在主节点出现故障时,由于集群需要临时选出一个新的主节点,因此数据库会不得不临时暂停写入操作。这就是所谓的单点故障。
相反,ScyllaDB和Cassandra属于“无领导”的P2P多活(Active-Active)系统。由于客户端可以读取或写入任何同构的节点,因此避免了单点故障。也就是说,每个节点都可以更新集群中任何其他副本的数据。
可见,虽然多活会带来更多的计算量,但是它解决了服务器保持彼此同步的问题。用户最终会得到一个适合重写入的负载平衡的系统,毕竟每个节点都可以提供读取与写入服务。
下面,我们看看上述5种数据库在主副本和P2P多活方面的表现:
CockroachDB和ScyllaDB(以及Cassandra)是按照多活模式设计的。
Postgres需要一些外部方法来实现多活,而并非内置。
MongoDB并不支持多活。
在Redis企业版中,我们可以使用无冲突的复制数据类型(conflict-free replicated data types,CRDT)来实现多活模式。
注意,Postgres、MongoDB和Redis都默认会使用主副本的数据分布模式。
复制
分布式系统设计也会影响到已部署的不同机架、或数据中心之间分配数据的方式。例如,在一套给定主副本系统中,只有拥有主节点的数据中心,才能服务于任何写入的负载。而其他数据中心只能作为只读副本。
而在支持多数据中心集群的对等系统中,整个集群中的每个节点都可以接受读取或写入负载。显然,这会更方便将工作负载分布到多个地理位置。
例如,通过使用ScyllaDB,您可以判定每个站点具有相同甚至不同的复制因子。在上图的右侧,我们展示了在一个数据中心拥有三个数据副本,而在另一个数据中心拥有两个副本的情况。
不同级别的操作会具有一致性。您可能在具有三节点的数据中心进行本地的“仲裁”式读取或写入(即:需要通过本地仲裁来更新三个节点中的哪两个)。当然,您也可能有一个集群范围内的仲裁,判定需要更新一个或两个数据中心里的任意三个节点。
拓扑感知
我们已经了解了分布式数据库的本地集群方式,它可以有效地让多个系统分担负载。您也可以跨多个地域节点对数据库进行分片,或是通过确保相同数据在多个节点上的高可用性,来保证数据的复制。
下面,让我们假设一个场景:如果您的所有节点都安装在同一个机架中,而整个机架出现了故障,那该怎么办呢?此时,我们需要用到同一数据中心内的机架拓扑感知,以确保将数据分布到该数据中心的多个机架中,从而最大限度地减少因电源或网络中断,而导致的整个机架与另一个机架失去连接。
在分布式数据库中,我们需要数据库的多个副本,运行在不同的数据中心上,以实现跨集群的更新机制。每个单一数据库都能够自主运行,而且它们的同步机制既可以是单向的(由一个数据中心去更新下游副本),也可以是双向或多向的。这种地理分布可以通过允许就近用户的连接,来最小化延迟,进而确保在出现单个数据中心的灾难时,用户不会丢失部分甚至全部数据。
下面,我们来看看上述5种数据库在拓扑感知方面的表现:
CockroachDB和ScyllaDB均有内置的拓扑感知特性。
MongoDB从2015年后开始引入拓扑感知特性。
Postgres和Redis最初被设计为单数据中心方案。虽然不是开箱即用的,但是您可以像添加多活功能那样,去手动添加拓扑感知服务。
下面,我们根据上述各项分布式特点,对5种数据库进行属性上的总结和对比。
PostgreSQL
Postgres是如今最流行的SQL实现之一。它提供了开箱即用的本地集群。不过,由于Postgres仍在致力于完善其多数据中心的集群,因此您需要通过额外的配置和开发,方可实现。
由于SQL建立在高度一致的事务性模式上,因此它不适合广泛地跨越地理区域的集群。每个查询都会被所有相关数据中心之间的长时间延迟而放大。
同时,Postgres依赖于主副本模型。集群中存在着主节点和副本节点的关系。您也可以额外地添加负载均衡器,或者多活附加组件。此外,Postgres虽然在自动化分片方面取得了一些进展,但是目前仍需要用户进行手动数据分片。
CockroachDB
作为“NewSQL”的CockroachDB不但使用了Postgres的传输协议(wire protocol),而且大量借鉴了许多由Postgres开创的概念。当然,它并没有局限于Postgres架构。例如:多数据中心集群和对等无领导拓扑,都被内置了进去。
此外,CockroachDB不但具有自动分片和数据复制功能,而且也内置了数据中心的感知能力,您可以按需添加机架的感知功能。
值得注意的是,由于CockroachDB需要所有的事务具有高度一致性,因此用户丧失了最终一致性或可调一致性(Tunable Consistency)的灵活度。这不但会降低吞吐量,而且会在任何跨数据中心的部署中,产生高基线的延迟(high baseline latencies)。
MongoDB
作为NoSQL典型代表的MongoDB,已被开发出了许多分布式数据库功能。例如,它已经能够实现多数据中心的集群了。虽然MongoDB在大多数情况下,仍然需要遵循主副本模式,但有用户可以通过第三方工具使其实现P2P的多活模式。
Redis
作为“键值对”存储的典型数据库,Redis旨在实现内存缓存或数据存储。虽然它可以持久化数据,但是如果数据集不适合内存的话,就会让性能大打折扣。
Redis在设计上默认考虑了本地集群。这会导致例如:一旦您无法在5毫秒内从SSD获取数据,就无法在145毫秒内完成从旧金山到伦敦的网络传输往返时间。当然,对于那些确实需要多地域分布存储的企业而言,它们仍然会在多数据中心里构建Redis集群。
同时,由于Redis往往是作为主副本模式运行的,因此它更适用于重读取的缓存服务器。也就是说,它需要数据被先写入,然后再分散到副本处,以平衡它们的缓存负载。
Redis的企业功能可以实现P2P的多活集群。同时,Redis能够自动分片和复制数据。不过,其拓扑感知功能仅限于带有企业特性的机架感知。
ScyllaDB
ScyllaDB是按照Apache Cassandra的分布式数据库模型设计的。默认情况下,它带有多数据中心集群,而且采取的是无领导的多活拓扑。
ScyllaDB会自动分片,并为每个操作提供了可调的一致性。如果您想获得更强的一致性,它也能够支持轻量级事务,并提供写入的线性化。
就拓扑感知而言,ScyllaDB支持机架感知和数据中心感知。它甚至支持令牌感知和分片感知,ScyllaDB不仅可以知晓该在哪个节点存储数据,而且可以获悉与该数据关联的CPU信息。
小结
在上文中,我们分析了五种知名的分布式数据库系统。其中,CockroachDB为SQL数据库提供了开箱即用的特性与属性的全面组合,而ScyllaDB为NoSQL系统提供了全面的功能。目前,分布式数据库仍在不断迭代与改进。它们正变得更加灵活、更具可扩展性、以及具有更高的性能。
译者介绍
陈峻 (Julian Chen),51CTO社区编辑,具有十多年的IT项目实施经验,善于对内外部资源与风险实施管控,专注传播网络与信息安全知识与经验;持续以博文、专题和译文等形式,分享前沿技术与新知;经常以线上、线下等方式,开展信息安全类培训与授课。
原文标题:Comparing Distributed Databases,作者:Peter Corless