为什么 RDBM 的集群不能像 NoSQL 那样?

fre*_*gas 89 nosql clustering scalability relational-theory

nosql DBMS 的一大优点是它们可以更轻松地进行集群。据称,使用 NoSQL,您可以创建数百台廉价的机器来存储不同的数据并一次查询所有数据。

我的问题是,为什么关系型 DBMS 不能像 mysql 或 sql server 那样做?是因为供应商还没有想出一种技术方法来使用他们现有的产品来做到这一点,还是关系模型存在一些问题阻止了这种做法的可行性?NoSQL 存储和访问数据(键/值、文档等)的方式有什么好处,使聚类更容易(如果这是真的)?

Con*_*lls 144

分布式数据库系统 101

或者,分布式数据库 - FK 的“网络规模”实际上意味着什么?

分布式数据库系统是复杂的小动物,有多种不同的风格。如果我深入研究我在大学里模糊记得的研究的深度,我将尝试解释构建分布式数据库系统的一些关键工程问题。

首先,一些术语

ACID(原子性、一致性、隔离性和持久性)属性:这些是必须强制执行的关键不变量,以便可靠地实现事务而不会引起不良副作用。

原子性要求事务完成或完全回滚。部分完成的交易不应该是可见的,并且系统必须以防止这种情况发生的方式构建。

一致性要求事务绝不能违反由数据库模式保证的任何不变量(例如声明性引用完整性)。例如,如果存在外键,则应该不可能插入子记录并尊重不存在的父记录。

隔离要求事务不应相互干扰。如果事务并行或顺序执行,系统应保证相同的结果。在实践中,大多数 RDBMS 产品允许在隔离与性能之间进行权衡的模式。

持久性要求事务一旦提交,就以一种对硬件或软件故障具有鲁棒性的方式保留在持久存储中。

我将在下面解释这些要求在分布式系统上存在的一些技术障碍。

共享磁盘架构:集群中的所有处理节点都可以访问所有存储的架构。这可能会成为数据访问的中心瓶颈。共享磁盘系统的一个示例是Oracle RACExadata

Shared Nothing Architecture:一种架构,其中集群中的处理节点具有其他集群节点不可见的本地存储。无共享系统的示例是TeradataNetezza

共享内存架构:多个 CPU(或节点)可以访问共享内存池的架构。大多数现代服务器都是共享内存类型。共享内存促进了某些操作,例如缓存或原子同步原语,这些操作在分布式系统上很难执行。

同步:一个通用术语,描述了确保多个进程或线程对共享资源的一致访问的各种方法。尽管某些网络架构(例如 Teradata 的 BYNET)在网络协议中具有同步原语,但在分布式系统上比在共享内存系统上更难做到这一点。同步也会带来大量开销。

半连接:用于连接分布式系统的两个不同节点中保存的数据的原语。本质上,它包含有关要连接的行的足够信息,这些行被捆绑起来并由一个节点传递到另一个节点以解析连接。在大型查询中,这可能涉及大量网络流量。

最终一致性:用于描述事务语义的术语,这些语义在分布式系统的所有节点上权衡立即更新(读取的一致性)以换取写入的性能(因此更高的事务吞吐量)。最终一致性是使用仲裁复制作为性能优化的副作用,以加快分布式数据库中的事务提交,其中多个数据副本保存在不同的节点上。

Lamport 算法:一种用于在没有共享内存的系统之间实现互斥(同步)的算法。通常,系统内的互斥需要原子读-比较-写或类似的指令,这种指令通常只适用于共享内存系统。存在其他分布式同步算法,但 Lamport 是最早的算法之一,也是最著名的算法。与大多数分布式同步机制一样,Lamport 的算法在很大程度上依赖于集群节点之间的准确计时和时钟同步。

两阶段提交 (2PC):一系列协议,可确保涉及多个物理系统的数据库更新一致地提交或回滚。无论 2PC 是在系统内使用还是通过事务管理器跨多个系统使用,它都会带来大量开销。

在两阶段提交协议中,事务管理器要求参与节点以他们可以保证提交的方式持久化事务,然后发出此状态的信号。当所有节点都返回“快乐”状态时,它会向节点发出提交信号。在所有节点都发送一个表示提交完成的回复之前,该事务仍然被认为是打开的。如果节点在发出提交完成的信号之前宕机,事务管理器将在节点恢复时重新查询节点,直到它得到表明事务已提交的肯定答复。

多版本并发控制 (MVCC):通过将数据的新版本写入不同位置并允许其他事务查看旧版本数据来管理争用,直到提交新版本。这减少了数据库争用,代价是一些额外的写入流量来编写新版本,然后将旧版本标记为过时。

选举算法:涉及多个节点的分布式系统本质上不如单个系统可靠,因为有更多的故障模式。在许多情况下,集群系统需要某种机制来处理节点故障。选举算法是一类算法,用于在“领导者”节点不是 100% 确定或可靠的情况下选择领导者以协调分布式计算。

水平分区:一个表可以通过它的键跨多个节点或存储卷进行拆分。这允许将大数据量拆分为更小的块并分布在存储节点之间。

分片:数据集可以在无共享架构中的多个物理节点之间进行水平分区。在这种分区不透明的情况下(即客户端必须知道分区方案并确定要明确查询的节点),这称为分片。一些系统(例如 Teradata)确实跨节点拆分数据,但位置对客户端是透明的;该术语通常不与此类系统结合使用。

一致性哈希:一种用于根据键将数据分配到分区的算法。它的特点是散列键分布均匀,并且能够有效地弹性扩展或减少桶的数量。这些属性使其可用于跨节点集群对数据或负载进行分区,其中节点的大小可以随着节点的添加或删除而动态变化(可能是由于故障)。

多主复制:一种允许跨集群中多个节点的写入复制到其他节点的技术。该技术允许跨服务器对某些表进行分区或分片,而其他表在整个集群中同步,从而促进了扩展。写入必须复制到所有节点,而不是仲裁,因此事务提交在多主复制架构上比在仲裁复制系统上更昂贵。

非阻塞交换机:一种网络交换机,它使用内部硬件并行来实现与端口数量成正比的吞吐量,没有内部瓶颈。一个简单的实现可以使用交叉机制,但是对于 N 个端口,这具有 O(N^2) 复杂度,将其限制为较小的交换机。较大的交换机可以使用更复杂的内部拓扑结构,称为非阻塞最小跨度交换机来实现线性吞吐量缩放,而无需 O(N^2) 硬件。

制作分布式 DBMS - 有多难?

一些技术挑战使得这在实践中很难做到。除了构建分布式系统的额外复杂性之外,分布式 DBMS 的架构师还必须克服一些棘手的工程问题。

分布式系统上的原子性:如果事务更新的数据分布在多个节点上,则必须协调节点的提交/回滚。这在无共享系统上增加了显着的开销。在共享磁盘系统上,这不是一个问题,因为所有节点都可以看到所有存储,因此单个节点可以协调提交。

分布式系统的一致性:以上面引用的外键示例为例,系统必须能够评估一致的状态。例如,如果外键关系的父子关系可以驻留在不同的节点上,则需要某种分布式锁定机制来确保不使用过时的信息来验证事务。如果不强制执行此操作,您可能会遇到(例如)竞争条件,其中在允许插入子项之前验证其存在后删除父项。

延迟执行约束(即等待提交以验证 DRI)需要在事务期间保持锁定。这种分布式锁定带来了巨大的开销。

如果持有多个数据副本(这在无共享系统上可能是必要的,以避免来自半连接的不必要的网络流量),则必须更新数据的所有副本。

分布式系统上的隔离:如果事务上受影响的数据驻留在多个系统节点上,则必须跨节点同步锁和版本(如果使用 MVCC)。保证操作的可串行性,特别是在可能存储冗余数据副本的无共享架构上需要分布式同步机制,例如 Lamport 算法,这也会带来大量的网络流量开销。

分布式系统的持久性在共享磁盘系统上,持久性问题与共享内存系统基本相同,不同之处在于仍然需要跨节点的分布式同步协议。DBMS 必须记录写入日志并一致地将数据写出。在无共享系统上,可能有多个数据副本或部分数据存储在不同节点上。需要一个两阶段提交协议来确保提交正确地跨节点发生。这也会导致显着的开销。

在无共享系统上,节点的丢失可能意味着系统无法使用数据。为了缓解这种情况,可以跨多个节点复制此数据。这种情况下的一致性意味着数据必须复制到它通常驻留的所有节点。这可能会导致大量的写入开销。

在 NoSQL 系统中进行的一个常见优化是使用仲裁复制和最终一致性,以允许延迟复制数据,同时通过在将事务报告为已提交之前写入仲裁来保证数据的一定程度的弹性。然后将数据延迟复制到数据副本所在的其他节点。

请注意,“最终一致性”是对一致性的主要权衡,如果一旦提交事务就必须一致地查看数据,则可能无法接受。例如,在财务应用程序中,更新后的余额应立即可用。

共享磁盘系统

共享磁盘系统是一种所有节点都可以访问所有存储的系统。因此,计算与位置无关。许多 DBMS 平台也可以在这种模式下工作 - Oracle RAC 就是这种架构的一个例子。

共享磁盘系统可以大幅扩展,因为它们可以支持存储节点和处理节点之间的 M:M 关系。一个 SAN 可以有多个控制器,多个服务器可以运行数据库。这些架构将交换机作为中心瓶颈,但纵横式交换机允许该交换机拥有大量带宽。一些处理可以卸载到存储节点上(如 Oracle 的 Exadata),这可以减少存储带宽上的流量。

尽管交换机理论上是一个瓶颈,但可用带宽意味着共享磁盘架构将非常有效地扩展到大交易量。大多数主流 DBMS 架构都采用这种方法,因为它提供了“足够好”的可扩展性和高可靠性。使用光纤通道等冗余存储架构时,不会出现单点故障,因为任何处理节点和任何存储节点之间至少有两条路径。

无共享系统

Shared-nothing 系统是这样一种系统,其中至少有一些数据在本地保存在一个节点上,并且对其他节点不直接可见。这消除了中央交换机的瓶颈,允许数据库根据节点数量进行扩展(至少在理论上)。水平分区允许跨节点拆分数据;这可能对客户端透明或不透明(参见上面的分片)。

由于数据本质上是分布式的,因此查询可能需要来自多个节点的数据。如果连接需要来自不同节点的数据,则使用半连接操作来传输足够的数据以支持从一个节点到另一个节点的连接。这会导致大量的网络流量,因此优化数据的分布会对查询性能产生很大的影响。

通常,数据在无共享系统的节点之间复制,以减少半连接的必要性。这在数据仓库设备上非常有效,因为维度通常比事实表小许多数量级,并且可以轻松地跨节点复制。它们通常也分批加载,因此与事务应用程序相比,复制开销不是一个问题。

无共享架构固有的并行性使它们非常适合数据仓库特有的表扫描/聚合查询类型。这种操作几乎可以随着处理节点的数量线性扩展。跨节点的大型连接往往会产生更多开销,因为半连接操作会产生大量网络流量。

移动大数据量对于事务处理应用程序来说不太有用,因为多次更新的开销使得这种类型的架构不如共享磁盘有吸引力。因此,这种类型的架构往往不会在数据仓库应用程序之外广泛使用。

分片、仲裁复制和最终一致性

仲裁复制是一种 DBMS 复制数据以实现高可用性的工具。这对于打算在没有内置高可用性功能(如 SAN)的廉价商品硬件上工作的系统很有用。在这种类型的系统中,数据跨多个存储节点复制,以提高读取性能和冗余存储,从而使系统对节点的硬件故障具有弹性。

但是,对于 M 个节点和 N 个写入,对所有节点的写入复制是 O(M x N)。如果在允许提交事务之前必须将写入复制到所有节点,则这会使写入变得昂贵。仲裁复制是一种折衷方案,允许立即将写入复制到节点的子集,然后通过后台任务延迟写入其他节点。写入可以更快地提交,同时通过确保在将事务报告为提交给客户端之前将它们复制到节点的最小子集(仲裁)来提供一定程度的冗余。

这意味着读取仲裁之外的节点可以看到数据的过时版本,直到后台进程完成将数据写入其余节点。语义被称为“最终一致性”,根据您的应用程序的要求可能会或可能不会被接受,但这意味着事务提交在资源使用方面更接近 O(1) 而不是 O(n)。

分片要求客户端了解数据库内数据的分区,通常使用一种称为“一致散列”的算法。在分片数据库中,客户端对键进行哈希处理以确定向集群中的哪个服务器发出查询。由于请求分布在集群中的节点之间,因此单个查询协调器节点不存在瓶颈。

这些技术允许数据库通过向集群添加节点以接近线性的速度扩展。从理论上讲,只有当底层存储介质被认为不可靠时,才需要仲裁复制。如果要使用商品服务器,这很有用,但如果底层存储机制具有自己的高可用性方案(例如具有镜像控制器和多路径连接到主机的 SAN),则价值较小。

例如,Google 的 BigTable 本身并没有实现仲裁复制,尽管它确实位于 GFS 上,这是一个使用仲裁复制的集群文件系统。BigTable(或任何无共享系统)可以使用具有多个控制器的可靠存储系统并在控制器之间对数据进行分区。然后将通过对数据进行分区来实现并行访问。

返回 RDBMS 平台

这些技术不能与 RDBMS 一起使用并没有内在的原因。然而,在这样的系统上,锁和版本管理会非常复杂,并且这种系统的任何市场都可能非常专业。主流 RDBMS 平台都没有使用仲裁复制,而且我不知道有任何 RDBMS 产品(至少没有任何显着采用的产品)这样做。

共享磁盘和无共享系统可以扩展到非常大的工作负载。例如,Oracle RAC 可以支持 63 个处理节点(它们本身可以是大型 SMP 机器)和 SAN 上任意数量的存储控制器。IBM Sysplex(zSeries 大型机集群)可以支持多个大型机(每个大型机都具有强大的处理能力和自己的 I/O 带宽)和多个 SAN 控制器。这些架构可以通过 ACID 语义支持非常大的事务量,尽管它们确实假设了可靠的存储。Teradata、Netezza 和其他供应商制造基于无共享设计的高性能分析平台,可扩展到超大数据量。

到目前为止,廉价但超高容量的完全 ACID RDBMS 平台的市场由 MySQL 主导,它支持分片和多主复制。MySQL 不使用仲裁复制来优化写入吞吐量,因此事务提交比在 NoSQL 系统上更昂贵。分片允许非常高的读取吞吐量(例如 Facebook 广泛使用 MySQL),因此这种类型的架构在读取繁重的工作负载上可以很好地扩展。

一场有趣的辩论

BigTable的是一个无共享架构(本质上是一个分布式键-值对),通过迈克尔Hausenblas指出以下。我最初对它的评估包括 MapReduce 引擎,它不是 BigTable 的一部分,但通常会在其最常见的实现(例如 Hadoop/HBase 和 Google 的 MapReduce 框架)中与它结合使用。

将此架构与 Teradata 进行比较,后者在存储和处理之间具有物理关联(即节点具有本地存储而不是共享 SAN),您可能会认为 BigTable/MapReduce 是通过全局可见的并行存储系统的共享磁盘架构。

Hadoop 等 MapReduce 风格系统的处理吞吐量受到非阻塞网络交换机带宽的限制。1 然而,由于设计中固有的并行性,非阻塞交换机可以处理大带宽聚合,因此它们很少对性能产生重大的实际约束。这意味着共享磁盘架构(也许更好地称为共享存储系统)可以扩展到大型工作负载,即使网络交换机理论上是一个中心瓶颈。

最初的观点是要注意,尽管共享磁盘系统中存在这个中心瓶颈,但具有多个存储节点(例如 BigTable 平板服务器或 SAN 控制器)的分区存储子系统仍然可以扩展到大型工作负载。非阻塞交换机架构(理论上)可以处理与端口一样多的当前连接。

1当然,可用的处理和 I/O 吞吐量也构成了性能限制,但网络交换机是所有流量通过的中心点。

  • 一些技术思想。事实上,仲裁复制是在 PostgreSQL 的主/从设置的流式复制上完成的。默认情况下,数据必须仅提交给主服务器,但您也可以要求在返回提交之前将其也写入 n 个从服务器。 (3认同)
  • @Michael Hausenblas 再想一想,如果您单独使用 BigTable DB,我会采用无共享声明。在本文中,我将它与整个 MapReduce/Hadoop 堆栈(处理和存储之间没有特定的关联)混为一谈。你可以相当合理地争论这种混淆的不恰当性。 (2认同)

小智 22

关系数据库可以像 NoSQL 解决方案一样集群。维护 ACID 属性可能会使这变得更加复杂,并且必须了解为维护这些属性所做的权衡。不幸的是,权衡究竟取决于工作负载,当然还有在设计数据库软件时所做的决定。

例如,即使集群的吞吐量很好地扩展,主要的 OLTP 工作负载也可能具有额外的单个查询延迟。额外的延迟可能会被忽视或成为真正的交易破坏者,这一切都取决于应用程序。一般来说,集群会提高吞吐量并减少延迟,但如果应用程序的查询特别适合并行处理,那么即使是这个“规则”也是值得怀疑的。

我工作的公司Clustrix提供的是一系列由相对高速网络连接的同计算和存储节点。关系数据散列分布在每个索引的节点上,以我们称为“切片”的块为单位。每个分片将有两个或多个副本分布在整个集群中,以在节点或磁盘发生故障时提供持久性。客户端可以连接到集群中的任何节点以使用 MySQL 线路协议发出查询。

独立思考 ACID 数据库的组件有点不自然,因为它的大部分内容都吻合在一起,但这里是:

原子性- Clustrix 使用两阶段提交来确保原子性。UPDATE 和 DELETE 操作也将通过我们的分布式锁管理器锁定行,因为我们在内部将这些操作转换为 SELECT,然后是精确的 UPDATE/DELETE 操作。

原子性显然增加了参与事务的节点之间的消息传递量,并增加了这些节点上处理提交协议的负载。这是分布式系统开销的一部分,如果每个节点都参与每个事务,则会限制可扩展性,但如果节点具有正在写入的副本之一,则它们仅参与事务。

一致性- 外键作为触发器实现,在提交时进行评估。由于锁定,大范围的 UPDATE 和 DELETE 操作可能会损害我们的性能,但幸运的是,我们并不经常看到这些。看到事务更新/删除几行然后提交的情况要常见得多。

一致性的另一部分是通过PAXOS 共识协议维护法定人数,以确保只有拥有大多数已知节点的集群才能进行写入。当然,集群可能有仲裁但仍然缺少数据(切片的所有副本离线),这将导致访问这些切片之一的事务失败。

隔离- Clustrix 在容器级别提供 MVCC 隔离。我们的原子性保证所有适用的副本在我们报告提交的事务之前都会收到特定的写入,这主要将隔离问题减少到非集群情况下的情况。

持久性- 关系数据的每个切片都存储到两个或多个节点,以在节点或磁盘出现故障时提供弹性。这里可能还值得注意的是,我们产品的设备版本有一个 NVRAM 卡,出于性能原因,WAL 存储在其中。许多单实例数据库将通过每隔一段时间而不是每次提交检查点来提高其 WAL 的性能。这种方法在分布式系统中是有问题的,因为“重播到哪里?” 一个复杂的问题。我们通过提供严格的耐用性保证来避免在设备中出现这种情况。


Chr*_*ers 15

根本的答案是一致性模型是不同的。我写这篇文章是为了扩展 ConcernedOfTunbridge 的答案,这真的应该是这个的参考点。

ACID 一致性模型的基本点是它对系统内全局数据的状态做出了一系列基本保证。这些保证受 CAP 定理限制,这意味着,基本上,要使它们起作用,在告诉应用程序您已提交事务之前,您需要在同一页面上拥有所有权威来源。因此,在不遇到这些限制的情况下,很难进行多主复制。当然,一旦您开始在多主环境中进行异步复制,这些保证就会消失。ACID 一致性模型是用于重要或关键信息的强一致性模型。

BASE 一致性模型是用于非关键信息的弱一致性模型。因为保证明显较弱,所以在多主系统中提供这种弱保证的能力更容易实现,因为保证很弱。

不过,RDBMS 可以并且确实可以和 NoSQL 解决方案一样扩展!

然而,在某些情况下,RDBMS 可以并且确实可以扩展到 NoSQL 甚至可能无法匹配的程度。它只是表现不同。我将以 Postgres-XC 为例说明如何在不牺牲强一致性保证的情况下进行扩展。

这些特定 RDBMS 的工作方式是实现某种类似于带有代理的分片解决方案和一种类似于共享磁盘架构的东西,但比两者都要复杂得多。它们的扩展方式与 NoSQL 解决方案不同,因此权衡不同。

据我所知,Postgres-XC 模型的灵感来自 Teradata。它由两个不同角色的节点组成,作为存储节点或协调器。协调器是多主的(不涉及真正的复制),它们连接到存储节点来处理实际的数据处理。存储节点以主从设置进行复制。每个存储节点包含本质上是数据库分片的内容,但协调器维护数据的一致画面。

这里涉及显着的职责分离。存储节点管理数据、检查约束、本地强制执行的外键约束,并至少处理一些数据聚合。协调器处理那些不能在本地执行的外键,以及可能从多个数据节点中提取的窗口和其他数据注意事项。本质上,协调器使 ACID 在多主设置中的分布式事务中成为可能,其中用户甚至不知道事务是分布式的。

在这方面,Postgres-XC 提供了一些类似于 NoSQL 扩展选项的东西,但由于额外的一致性保证,增加了一些复杂性。我知道有一些商业 RDBMS 可以提供这种可扩展性。Teradata 就是这样做的。此外,共享磁盘系统可以以类似的方式横向扩展,DB2 和 Oracle 都提供此类解决方案。所以说 RDBMS 不能做到这一点是完全不公平的。他们能。然而,过去的需求非常小,以至于规模经济不足以使大多数参与者负担得起专有解决方案。

最后是关于 VoltDB 的说明。与 NoSQL 解决方案一样,我将 VoltDB 视为一种非常专业的工具。它非常快,但以多往返事务和磁盘持久性为代价。这意味着您有一系列非常不同的担忧。当 RDBMS 先驱者构建 NoSQL 解决方案时,您会得到 VoltDB ;-)。VoltDB 速度很快,部分原因是它在等式之外定义了并发性和持久性。持久性成为一种网络属性,而不是主机内属性,并发性是通过一次一个、内部并行、按顺序运行的查询来管理的。它不是传统的 RDBMS(顺便说一句,这是一件好事,因为它可以去传统 RDBMS 不能去的地方,但反过来也是如此)。

编辑: 考虑连接的含义也很重要。在集群系统中,连接成为一个非常不同的性能问题。如果一切都在同一个节点上,它们可以提高性能,但是如果您必须往返于不同的节点,这会带来非常高的成本。因此,数据模型确实有所不同,并且聚类方法会影响性能。像 Postgres-XC 和 Postgres-XL 这样的方法假设您可以花相当多的时间思考问题,以便您可以适当地分片数据并将连接的数据保持在一起。但这会增加设计开销。另一方面,这比许多 NoSQL 解决方案的可扩展性要好得多,并且可以进行适当的调整。例如,我们(在 Adjust)对 PostgreSQL 中的 3.5PB 数据使用类似 NoSQL 的集群策略,这基本上是日志分析。我们的很多设计都深受 NoSQL 集群策略的启发。所以有时数据模型也会约束聚类模型。


小智 6

我的答案不会像前一个那样写得好,但这里是。

Ingres 的 Michael Stonebraker 创建了一个 MPP 无共享列存储(Vertica)和一个 MPP 无共享新 SQL 数据库(VoltDB),它在集群中的不同节点之间分配数据并维护 ACID。Vertica 已被惠普收购。

我相信其他新的 SQL 数据库也维护 ACID,尽管我不确定它们中有多少将它们的行分布在集群上,等等。

这是 Stonebraker 就新 SQL 与 NoSQL 和“旧 SQL”进行的一次谈话。http://www.youtube.com/watch?v=uhDM4fcI2aI

  • 这个“新 SQL”和“旧 SQL”是什么?你愿意澄清吗? (2认同)