NodeCitus是一个PostgreSQL扩展,它允许数据库服务器(称为节点)在“无共享”架构中相互协调。这些节点形成一个集群,使PostgreSQL可以存储更多的数据并使用比单台计算机更多的CPU内核。这种架构还允许通过简单地向集群添加更多节点来扩展数据库。Extensionshttps://www.postgresql.org/docs/current/external-extensions.htmlCoordinator和Worker每个集群都有一个特殊的节点,称为协调器(coordinator)(其他节点称为工作节点)。应用程序将它们的查询发送到协调器节点,协调器节点将它们转发给相关的工作人员并累积结果。对于每个查询,协调器要么将其路由到单个工作节点,要么将其并行化到多个节点,具体取决于所需数据是驻留在单个节点上还是跨多个节点。协调器通过查阅其元数据表知道如何执行此操作。这些特定于Citus的表跟踪工作节点的DNS名称和健康状况,以及跨节点的数据分布。分布式数据表类型Citus集群中有三种类型的表,每种表在节点上的存储方式不同,用于不同的目的。类型1:分布式表第一种也是最常见的类型是分布式表。它们看起来是SQL语句的普通表,但在工作节点之间水平分区。这里表的行存储在工人表table_1001、table_1002等中。组件工人表称为分片。分布列Citus使用分片算法将行分布到分片。分配是根据表列(称为分布列)的值确定性地执行的。集群管理员在分配表时必须指定此列。做出正确的选择会对性能和功能产生重大影响。类型2:引用表引用表是一个分布式表,其全部内容被收集到一个单独的分片中,并在每个worker上复制。因此,对任何工作人员的查询都可以在本地访问参考信息,而无需从另一个节点请求行,因此不会产生此类网络开销。引用表没有分布列,因为不需要为每一行区分单独的分片。引用表通常很小,用于存储与在任何工作节点上运行的查询相关的数据。例如,订单状态或产品类别等枚举值。与引用表交互时,我们会自动对事务执行两阶段提交(2PC)。这意味着Citus确保您的数据始终处于一致的状态,无论您是在写入、修改还是删除它。2PChttps://en.wikipedia.org/wiki/Two-phase_commit_protocol类型3:本地表当您使用Citus时,您连接并与之交互的协调器节点是安装了Citus扩展的常规PostgreSQL数据库。因此,您可以创建普通表并选择不对其进行分片。这对于不参与连接查询的小型托管表很有用。一个示例是用于应用程序登录和身份验证的用户表。创建标准PostgreSQL表很容易,因为它是默认的。这是您在运行CREATETABLE时得到的结果。在几乎每个Citus部署中,我们都会看到标准PostgreSQL表与分布式表和参考表共存。事实上,如前所述,Citus本身使用本地表来保存集群元数据。分片上一节将分片描述为包含工作节点内较小表中分布式表行的子集。本节详细介绍技术细节。协调器上的pg_dist_shard元数据表包含系统中每个分布式表的每个分片的一行。该行与分片ID匹配,分片ID的范围是一组散列整数(shardminvalue、shardmaxvalue)。从pg_dist_shard选择*;逻辑依赖|碎片|分片存储|分片值|shardmaxvalue----------------+--------+----------------+--------------+----------------github_events|102026|吨|268435456|402653183github_事件|102027|吨|402653184|536870911github_事件|102028|吨|536870912|671088639github_事件|102029|吨|671088640|算法。然后该节点检查哪个分片的范围包含此哈希。定义范围后,哈希函数的图像(image)就是两者的结合。分片放置假定分片102027与相应的行相关联。在工作人员的github_events_102027表中读取或写入此行。哪个工人?这完全由元数据表决定。将分片映射到工人的过程称为分片放置。协调器节点将查询重写为引用特定表(例如github_events_102027)的片段,并针对相应的工作人员运行这些片段。下面的查询示例在后台运行以查找分片ID为102027的节点。SELECTshardid,node.nodename,node.nodeportFROMpg_dist_placementJOINpg_dist_nodenodeONplacement.groupid=node.groupidANDnode.noderole='primary'::noderoleWHEREshardid=102027;┌────────────┬──────────────┬────────────┐│shardid│节点名│节点端口│├─────────────────────────────────────────────────────────────┼────────────┤│102027│localhost│5433│└────────────┴────────────────────────────────────────┘在github_events的例子中,有四个分片。每个表的分片数量是可配置的,因为它分布在集群中。最后请注意,Citus允许复制分片以防止数据丢失。有两种复制“模式”:Citus复制和流式复??制。前者创建额外的备份分片放置并对所有更新它们的查询运行查询。后者效率更高,利用PostgreSQL的流式复制将每个节点的整个数据库备份到一个follower数据库。这是透明的,不需要Citus元数据表的参与。共置由于分片及其副本可以根据需要放置在节点上,因此将包含相关表的相关行的分片放在同一节点上是有意义的。这样,它们之间的连接查询就避免了通过网络发送尽可能多的信息,并且可以在单个Citus节点内执行。一个例子是包含商店、产品和采购的数据库。如果所有三个表都包含store_id列并由它们分布,那么所有限制在单个商店的查询都可以在单个工作节点上高效运行。即使查询涉及这些表的任意组合也是如此。并行性跨多台机器传播查询允许一次运行更多查询,并允许通过向集群添加新机器来扩展处理速度。此外,如前一节所述,将单个查询拆分为片段可以增加专用于它的处理能力。后一种情况实现了最大的并行性,这意味着CPU内核的利用率。读取或影响均匀分布在多个节点上的分片的查询可以“实时”速度运行。注意,查询的结果仍然需要通过协调器节点传回,所以当最终结果比较紧凑时(比如计数和描述性统计等聚合函数),提速最为明显。查询执行在执行多分片查询时,Citus必须平衡并行性的好处与数据库连接的开销(网络延迟和工作节点资源使用)。要配置Citus的查询执行以获得最佳数据库工作负载结果,有助于了解Citus如何管理和维护协调器和工作节点之间的数据库连接。Citus将每个传入的多分片查询会话转换为称为任务的每个分片查询。它对任务进行排队,并在可以连接到相关工作节点时运行它们。对于分布式表foo和bar的查询,这里是连接管理图:协调器节点为每个会话都有一个连接池。每个查询(例如图中的SELECT*FROMfoo)仅限于为每个工作任务打开最多citus.max_adaptive_executor_pool_size(整数)个同时连接。此设置可在会话级别配置以进行优先级管理。在同一个连接上顺序执行短任务比为它们并行建立新连接要快。另一方面,长时间运行的任务受益于更直接的并行性。为了平衡短任务和长任务的需求,Citus使用citus.executor_slow_start_interval(integer)。此设置指定多分片查询中任务的连接尝试之间的延迟。当查询第一次排队任务时,这些任务只能获取一个连接。在每个挂起连接间隔结束时,Citus会增加它将打开的同时连接数。通过将GUC设置为0可以完全禁用慢启动行为。当任务完成使用连接时,会话池将保持连接打开以供以后使用。缓存连接避免了在协调器和工作者之间重新建立连接的开销。但是,每个池一次最多打开citus.max_cached_conns_per_worker(整数)个空闲连接,以限制工作人员中空闲连接资源的使用。最后,设置citus.max_shared_pool_size(整数)作为故障保护。它限制了所有任务中每个工作人员的连接总数。
