「PostgreSQL架构」揭秘:为何关系型数据库将引领分布式数据库的未来?

发表时间: 2020-01-28 12:27

大约10年前,我加入了Amazon Web Services,在那里我第一次看到了在分布式系统中进行权衡的重要性。在大学里,我已经了解了一致性和可用性之间的权衡(CAP定理),但实际上,频谱要比这深得多。任何设计决策都可能涉及延迟,并发性,可伸缩性,耐用性,可维护性,功能性,操作简便性以及系统其他方面之间的权衡,而这些权衡会对应用程序的功能和用户体验产生有意义的影响,并且即使是业务本身的有效性。

也许在权衡需求最明显的分布式系统中最具挑战性的问题是构建分布式数据库。当应用程序开始需要可以在许多服务器上扩展的数据库时,数据库开发人员开始做出极端的权衡。为了在许多节点上实现可伸缩性,分布式键值存储(NoSQL)抛弃了传统关系数据库管理系统(RDBMS)提供的丰富功能集,包括SQL,联接,外键和ACID保证。由于每个人都想要可伸缩性,因此RDBMS消失只是时间问题,对吗?实际上,关系数据库继续主导着数据库领域。这就是为什么:

在分布式系统(或任何系统)中进行权衡时,要考虑的最重要方面是开发成本。

数据库软件所做出的权衡将对应用程序的开发成本产生重大影响。在高级应用程序中处理需要可用性,可靠性和性能的数据是一个固有地需要解决的问题。成功解决每个小问题所需的工时数量可能很大。幸运的是,数据库可以解决许多这些子问题,但是数据库开发人员也面临成本问题。实际上,要使数据库足以满足大多数应用程序的功能,保证和性能,就需要数十年的时间。那就是建立关系数据库如PostgreSQL和MySQL的地方。

在Citus Data,我们从不同角度解决了数据库可伸缩性的需求。我和我的团队在过去的几年中花费了很多时间将已建立的RDBMS转换为分布式数据库,而又不会失去其强大功能或从基础项目中分叉。通过这样做,我们发现RDBMS是构建分布式数据库的理想基础。

通过在RDBMS之上构建来降低应用程序开发成本

使RDBMS对开发应用程序(尤其是开源RDBMS,尤其是云RDBMS)如此吸引人的原因在于,您可以有效地利用数十年来对RDBMS进行的工程投资,并利用这些RDBMS功能。您的应用,降低了开发成本。

RDBMS为您提供:

  1. 围绕数据完整性和持久性的有意义的保证
  2. 极大的灵活性来操纵和查询数据
  3. 最先进的算法和数据结构,可在各种工作负载下获得高性能。

这些功能几乎对任何非平凡的应用都很重要,但是要花很长时间才能开发。另一方面,某些应用程序的工作量对于单台计算机来说太过苛刻,因此需要水平可伸缩性。

许多新的分布式数据库正在开发中,并且正在分布式键值存储(“ NewSQL”)之上实现RDBMS功能,例如SQL。尽管这些较新的数据库可以使用多台计算机的资源,但是在SQL支持,查询性能,并发性,索引,外键,事务,存储过程等方面,它们仍远未建立在关系数据库系统上。您遇到许多要在应用程序中解决的复杂问题。

许多大型互联网公司采用的替代方法是RDBMS的手动,应用程序层分片(通常是PostgreSQL或MySQL)。手动分片意味着有许多RDBMS节点,并且应用程序会根据某种条件(例如,用户ID)决定连接到哪个节点。应用程序本身负责如何处理数据放置,架构更改,查询多个节点,复制表等,因此,如果执行手动分片,最终将在应用程序中实现自己的分布式数据库,这可能甚至更多。昂贵。

幸运的是,有一种方法可以解决开发成本难题。

PostgreSQL已有数十年的发展历史,其令人难以置信的重点是代码质量,模块化和可扩展性。这种可扩展性提供了一个独特的机会:无需分叉就可以将PostgreSQL转换为分布式数据库。这就是我们构建Citus的方式。

Citus:成为世界上最先进的分布式数据库

大约5年前,当我加入一家名为Citus Data的初创公司时,我为在竞争激烈的市场中建立高级分布式数据库而无任何现有基础架构,品牌知名度,进入市场,资本或大量工程师的挑战感到沮丧 。 仅开发成本就似乎是无法克服的。 但是,就像应用程序开发人员利用PostgreSQL来构建复杂的应用程序一样,我们利用PostgreSQL来构建……分布式PostgreSQL。

我们创建了Citus,这是开源的PostgreSQL扩展,而不是从头开始创建分布式数据库,它以提供水平扩展的方式透明地分发表和查询,但是应用程序开发人员需要具备所有PostgreSQL功能才能成功。

通过使用在计划查询时Postgres调用的内部挂钩,我们能够将分布式表的概念添加到Postgres。


分布式表的分片存储在具有所有现有功能的常规PostgreSQL节点中,Citus发送常规SQL命令以查询分片,然后合并结果。 我们还添加了参考表的概念,该参考表可在所有节点上复制,因此可以通过任何列与分布式表连接。 通过进一步增加对分布式事务,查询路由,分布式子查询和CTE,序列,更新等的支持,我们达到了最先进的PostgreSQL功能可以使用的规模,但现在已经可以大规模使用。

Citus相对来说还很年轻,但是已经建立在PostgreSQL之上,已经成为世界上最先进的分布式数据库之一。与PostgreSQL的完整功能集相比,这令人毛骨悚然,还有许多工作要做,Citus现在提供的功能及其扩展方式使其在分布式数据库环境中具有很大的独特性。许多当前的Citus用户最初使用Postgres中的许多高级功能在单节点PostgreSQL服务器上建立业务,然后仅用几周的开发工作就迁移到Citus,以将其数据库模式转换为分布式表和引用表。对于任何其他数据库,从单节点数据库到分布式数据库的这种迁移可能要花费数月甚至数年的时间。

使用Citus将Postgres功能转变为超级强大

像PostgreSQL这样的RDBMS具有几乎无限的功能和成熟的SQL引擎,可让您以多种方式查询数据。当然,这些功能只有在速度很快时才对应用程序有用。幸运的是,PostgreSQL很快,并且通过诸如实时查询编译之类的新功能不断提高,但是当您拥有大量数据或流量以至于一台机器速度太慢时,那些强大的功能就不再那么有用了……除非您可以结合许多计算机的计算能力。这就是功能成为超级大国的地方。

通过采用PostgreSQL功能并进行扩展,Citus具有许多超级功能,这些功能使用户可以将数据库扩展到任意大小,同时保持高性能及其所有功能。

  • 查询路由意味着获取查询(作为查询的一部分),并让存储相关分片的RDBMS节点处理查询,而不是收集或重新整理中间结果,当查询通过分发列进行过滤和合并时,这是可能的。查询路由使Citus能够为多租户(SaaS)应用程序大规模支持底层PostgreSQL服务器的所有SQL功能,这些应用程序通常按租户ID进行过滤。就分布式查询计划时间和网络流量而言,此方法具有最小的开销,可实现高并发性和低延迟。
  • 与顺序执行相比,跨分布式表中所有分片的并行,分布式SELECT允许您在短时间内查询大量数据,这意味着您可以构建具有一致响应时间的应用程序,即使您的数据和客户数量通过扩展数据库来增长。 Citus查询计划程序将从多个分片中读取数据的SELECT查询转换为一个或多个类似于map-reduce的步骤,其中并行查询每个分片(map),然后合并或重新组合结果(reduce)。对于线性比例尺,大多数工作应在映射步骤中完成,对于联接或按分布列分组的查询通常是这种情况。
  • 联接是SQL的重要组成部分,其原因有两个:1)它们提供了极大的灵活性,可以以不同的方式查询数据,从而避免了应用程序中复杂的数据处理逻辑; 2)它们使您的数据表示更加紧凑。 。如果没有联接,则需要在每一行中存储大量冗余信息,这将大大增加存储,扫描表或将其保留在内存中所需的硬件数量。通过联接,您可以存储紧凑的不透明ID并进行高级过滤,而不必读取所有数据。
  • 参考表看起来像其他任何表一样,但是它们在群集中的所有节点之间透明地复制。在典型的星型模式中,所有维表都将是参考表,而事实表则是分布式表。然后,事实表可以与任何列上的任何维表结合(并行!),而无需通过网络移动任何数据。在多租户应用程序中,参考表可用于保存在租户之间共享的数据。
  • 子查询下推是并行,分布式SELECT,查询路由和联接之间的结合。可以通过子查询下推在单个回合中并行化包含高级子查询树的所有分片中的查询(例如子查询之间的联接),只要它们可以联接分布列上的所有分布式表(而引用表可以在任何列上联接)。这将启用非常高级的分析查询,该查询仍具有线性可伸缩性。 Citus可以利用PostgreSQL计划程序已经对所有查询进行的转换来识别可下推的子查询,并为所有剩余的子查询生成单独的计划。这允许有效地分布所有子查询和CTE。
  • 索引就像桌子的腿。没有它们,要从桌子上拿东西会很费力,而且实际上不是桌子。 PostgreSQL特别提供了非常强大的索引功能,例如部分索引,表达式索引,GIN,GiST,BRIN和覆盖索引。这使查询(包括联接!)即使在大规模时也能保持快速。值得记住的是,索引查找通常比扫描数据的一千个内核快。 Citus通过索引各个分片来支持所有PostgreSQL索引类型。像Heap和Microsoft这样的高级用户尤其喜欢使用部分索引来处理针对许多不同事件类型的各种查询。
  • 分布式事务允许您一次或根本不进行一组更改,这大大提高了应用程序的可靠性。 Citus可以使用类似于查询下推的方法将事务委派给PostgreSQL节点,并继承其ACID属性。对于跨碎片的交易,Citus使用PostgreSQL的内置2PC机制,并添加了一个分布式死锁检测器,该检测器使用PostgreSQL内部函数从所有节点获取锁表。
  • 并行,分布式DML允许以相对较少的时间和事务方式转换和维护大量数据。分布式DML的常见应用是INSERT…SELECT命令,该命令将原始数据表中的行聚合到汇总表中。通过在所有可用内核上并行执行INSERT…SELECT,数据库将始终足够快以聚集传入的事件,而应用程序(例如仪表板)将查询紧凑的,高索引的汇总表。另一个例子是Citus用户,他吸收了260亿行不良数据,并使用分布式更新对其进行了修复,平均每秒修改了70万行。
  • 批量加载是分析大量数据的应用程序的一项基本功能。即使在单个节点上,PostgreSQL的COPY命令也可以每秒向表追加数十万行,这已经超过了大多数分布式数据库基准测试。 Citus可以散出COPY流,以在许多PostgreSQL服务器上并行添加和索引许多行,这可以扩展到每秒数百万行。
  • 存储过程和函数(包括触发器)在数据库内部提供了一个编程环境,用于实现单个SQL查询无法捕获的业务逻辑。当您需要一组操作来进行事务处理而无需在应用程序服务器和数据库之间来回移动时,对数据库进行编程的功能特别有用。使用存储过程可以简化您的应用程序,并使数据库更高效,因为您可以避免在进行网络往返时保持事务打开。尽管它可能会给数据库带来更多的负载,但是在数据库扩展时,这将不再是一个大问题。

尽管大多数这些功能对于开发需要扩展的复杂应用程序来说似乎都是必不可少的,但并不是所有分布式数据库都支持它们。下面我们根据公开提供的文档对一些流行的分布式数据库进行比较。

让我们的力量结​​合起来……

与在分布式数据库中拥有超级功能相比,更重要的是能够组合数据库超级功能来解决复杂的用例。

由于支持查询路由,参考表,索引,分布式事务和存储过程,因此即使最先进的多租户OLTP应用程序(例如Copper)也可以使用Citus扩展到单个PostgreSQL节点之外,而不会在应用程序中做出任何牺牲。

如果将子查询下推与并行的分布式DML结合使用,则可以在数据库内部转换大量数据。一个常见的示例是使用INSERT…SELECT构建汇总表,该表可以并行化以适应任何类型的数据量。结合通过COPY,索引,联接和分区进行的批量加载,您将拥有一个非常适合时间序列数据和实时分析应用程序(如Algolia仪表板)的数据库。

正如Microsoft的Min Wei在谈到Microsoft如何使用Citus和PostgreSQL分析Windows数据时指出的那样:Citus使您能够使用分布式OLTP解决大规模OLAP问题。

GoodOldSQL

Citus与其他分布式数据库有些不同,后者通常是从头开始开发的。 Citus没有引入PostgreSQL中尚未提供的任何功能。 Citus数据库以满足需要扩展的用例的方式扩展了现有功能。重要的是,大多数PostgreSQL功能已经针对各种用例进行了数十年的开发和测试,而当今用例的功能要求最终并没有太大不同;主要是数据的规模和大小不同。因此,在构建现代应用程序时,基于世界上最先进的开源RDBMS(PostgreSQL!)构建的分布式数据库(如Citus)可以成为您的武器库中最强大的工具。

原文:
https://www.citusdata.com/blog/2018/11/30/why-rdbms-is-the-future-of-distributed-databases/

本文:
http://jiagoushi.pro/node/929

讨论:请加入知识星球或者微信圈子【首席架构师圈】