Citus 是一个完全作为开源 PostgreSQL 扩展构建的分布式数据库。事实上,您可以在不更改任何 PostgreSQL 功能的情况下将其安装在您的 PostgreSQL 服务器中。Citus 只是赋予 PostgreSQL 额外的超能力。
作为扩展也意味着我们可以继续高速添加新的 Postgres 功能。在上一个版本(11.0)中,我们专注于让您能够从任何节点查询,为许多新的用例开放 Citus,我们还使 Citus 完全开源。这意味着您可以在Citus GitHub 页面上看到我们所做的一切(如果您是粉丝,请为 repo 加注星标😊)。这也意味着每个人都可以利用分片重新平衡而无需停机。
在最新版本 (11.1) 中,我们在 Microsoft 的 Citus 数据库团队改进了应用程序的体验,并避免了在分发表和租户隔离等重要操作期间阻塞写入。这些新功能建立在从开发分片重新平衡器中获得的经验之上,它使用逻辑复制来避免阻塞写入。此外,我们使分片重新平衡器更快、更友好;此外,我们为即将发布的 PostgreSQL 15 版本做好了准备。这篇文章让您快速了解 Citus 11.1 的主要变化,包括:
- 在不阻塞写入的情况下分发 Postgres 表(横向扩展 Postgres!)
- 在不阻塞写入的情况下隔离租户
- 通过在不阻塞写入的情况下拆分分片来增加分片数量
- 无需等待即可在后台重新平衡集群
- PostgreSQL 15 (beta4) 支持
如果您想了解 Citus 11.1 中更改的全部详细信息,请查看我们的更新页面。
使用 create_distributed_table_concurrently 不间断地进行表分片
如果您想开始使用 Citus 扩展 Postgres 时需要知道一件事,那就是您可以使用 Citus UDF 进行表分片:
SELECT create_distributed_table('table_name',
'distribution_column');
当您调用该create_distributed_table函数时,Citus 会将您的数据分布在一组分片(常规 PostgreSQL 表)上,这些分片可以放置在单个节点上或跨多节点集群的工作节点上。之后,Citus 立即开始跨分片路由和并行化查询。如果您不调用create_distributed_table,Citus 根本不会改变 PostgreSQL 的行为,因此您仍然可以针对您的 Citus 协调器运行任何 PostgreSQL 工作负载。

图 1:开始使用 Citus 的方法是创建一个常规 PostgreSQL 表,然后运行 create_distributed_table,这会在工作节点(或同一个节点,如果是单节点集群)上创建分片
为了使表分片的体验尽可能无缝,create_distributed_table立即将表中已有的所有数据复制到分片中,这意味着如果您已经将数据插入到 PostgreSQL 表中,则不必从头开始。为避免丢失任何同时进行create_distributed_table的写入,请在复制数据时阻止对表的写入。
Citus 11.1 引入了使用名为的新函数分发表_而不阻塞写入_create_distributed_table_concurrently的能力: .
与CREATE INDEX CONCURRENTLY类似,您一次只能运行一个create_distributed_table_concurrently,在事务之外,但您的应用程序将在数据分发时继续平稳运行。类似于Citus shard rebalancer shard rebalancer,create_distributed_table_concurrently建立在逻辑复制之上,将数据复制期间发生的写入发送到正确的分片中。
图 2: 运行示例
create_distributed_table_concurrently。应用程序可以在表分发时继续写入表,最后只看到一个短暂的延迟。动图查看地址:https://www.citusdata.com/assets/images/blog/citus11_create_distributed_table_concurrently_810x540.webm
在不阻塞写入的情况下跨集群分布表是一个非常神奇的过程,但要记住一些限制:
- 如果您的表上没有主键/副本身份,则
create_distributed_table_concurrently由于逻辑复制的限制,更新和删除命令会失败。我们正在为 PostgreSQL 16 开发一个补丁来解决这个问题。 - 您不能
create_distributed_table_concurrently在事务块中使用,这意味着您一次只能分发一个表(但时间分区表可以工作!) create_distributed_table_concurrently当表被外键引用或引用另一个本地表时,您不能使用(但引用表的外键有效!您可以在之后为其他分布式表创建外键)
在多租户应用程序中隔离大型租户而不会中断
Citus 通常用于多租户应用程序,这些应用程序按租户 ID 分发和共同定位所有表。在某些情况下,其中一个租户比其他租户大得多,从而导致集群不平衡。
支持的低级逻辑复制基础架构create_distributed_table_concurrently也可用于将大型租户隔离到自己的分片中而无需停机。isolate_tenant_to_new_shard是一个现有的函数,它将单个哈希值通常对应于按租户 ID 分布的表中的单个租户拆分为同一节点上的自己的分片。这样,Citus shard rebalancer可以更均匀地分配数据,您还可以将租户移动到自己的节点。
在 Citus 11.1 之前,isolate_tenant_to_new_shard在操作期间阻止写入,但您并不想为最重要的租户中断应用程序中的写入。在 Citus 11.1 中,相同的函数变成了允许写入持续到结束的操作:
-- isolate tenant 293 to its own shard group
select isolate_tenant_to_new_shard('observations', 293);
图 3: 具有大型租户的数据库导致分片大小倾斜。我们在继续查询(包括写入)时隔离此租户。操作完成后,原始分片被拆分为 3 个,以便在集群中更好地平衡。动图查看地址:https://www.citusdata.com/assets/images/blog/citus11_tenant_isolation_short_810x540.webm
租户隔离操作后,rebalancer 可以将租户与其他分片分开移动,从而实现集群的平衡。您还可以使用citus_move_shard_placement函数将租户移动到自己的节点,或定义自定义重新平衡策略。
通过不间断地拆分分片来增加大型集群中的分片数量
create_distributed_table_concurrently两者背后的底层基础设施isolate_tenant_to_new_shard被称为“分片拆分”。
分片拆分基础架构更通用,并通过citus_split_shard_by_split_points函数公开,该函数将一个分片组(一组位于同一位置的分片)拆分为放置在不同节点上的任意散列范围。
您可以做的一件事citus_split_shard_by_split_points是增加非常大的集群中的分片数量,并精确控制新分片的放置位置。默认情况下,Citus 创建具有 32 个分片的分布式 Postgres 表——允许表分布在多达 32 个节点上。当您超出此限制时,最好有一种方法来拆分分片而无需停机:
-- split the shard group to which shard 102008 belongs into two pieces on node 2 and 3:
-- (see the nodeid column in the pg_dist_node catalog table)
select citus_split_shard_by_split_points(
shardid,
/* pick the split points, in this case we take the middle of the hash range*/
array[(shardminvalue::int + (shardmaxvalue::int - shardminvalue::int) / 2)::text],
/* send first half to node 2, second half to node 3 */
array[2, 3],
shard_transfer_mode := 'auto')
from pg_dist_shard
where shardid = 102008; /* shard to split (along with all co-located shards) */
当单个分片组开始超过单个节点时,拆分分片的能力也可以成为救命稻草。未来,我们计划为分片拆分提供更方便、自动化的 API,但拥有底层功能已经可以在紧急情况下提供帮助。
分片拆分建立在逻辑复制之上。当逻辑复制处于活动状态时,如果没有副本身份(例如主键),更新/删除查询将失败。默认情况下,如果要拆分的表之一没有副本标识,则拆分和隔离函数会引发错误,以防止意外停机。好消息是,没有主键的表类型通常不是经常更新的表类型。shard_transfer_mode := 'force_logical'您可以通过传递参数允许拆分继续进行逻辑复制。您还可以在 split 期间阻止所有写入shard_transfer_mode := 'block_writes',这会跳过逻辑复制步骤并且可以更快一些。
我们将在以后的博客文章中分享更多关于我们如何使逻辑复制适用于分片拆分的详细信息。
在后台更快地重新平衡分片
横向扩展 Citus 数据库集群传统上是一个两步过程:
- 向 Citus 集群添加新节点
- 通过调用
rebalance_table_shards()SQL 函数重新平衡分片
重新平衡使用逻辑复制在节点之间移动分片组以避免阻塞写入。
我们要求您单独进行重新平衡有几个原因。其中之一是防止某些表没有主键并且设置逻辑复制会导致更新/删除失败的情况。另一个原因是您可能希望在一天中较安静的时间重新平衡,以确保它不会与峰值负载竞争资源。
到目前为止,重新平衡的一个更烦人的方面是该rebalance_table_shards功能可能需要很长时间才能完成,并且您必须始终保持 PostgreSQL 连接打开,并检查是否有故障,这在长时间运行的数据移动期间偶尔会发生. 幸运的是,Citus 11.1 引入了一种运行分片重新平衡器的新方法,该方法将单个分片移动放置在专用的后台作业队列中,让您一劳永逸。
当您在 11.1 中调用新citus_rebalance_start函数时,会安排一个重新平衡作业,该作业可以包含多个分片组移动任务,以使集群进入平衡状态。每次移动都会重试几次以防失败,您可以在任务队列中跟踪进度,并轻松取消。
-- Kick off a rebalance job, completes immediately and returns the job ID
SELECT citus_rebalance_start();
┌───────────────────────┐
│ citus_rebalance_start │
├───────────────────────┤
│ 6 │
└───────────────────────┘
(1 row)
-- view the job status
SELECT state, job_type, started_at, finished_at FROM pg_dist_background_job WHERE job_id = 6;
┌─────────┬───────────┬───────────────────────────────┬─────────────┐
│ state │ job_type │ started_at │ finished_at │
├─────────┼───────────┼───────────────────────────────┼─────────────┤
│ running │ rebalance │ 2022-09-18 17:14:35.862386+02 │ │
└─────────┴───────────┴───────────────────────────────┴─────────────┘
(1 row)
-- inspect the individual move tasks
-- (blocked tasks are waiting for the running move)
SELECT task_id, status, command FROM pg_dist_background_task WHERE job_id = 6 ORDER BY task_id DESC;
┌─────────┬─────────┬───────────────────────────────────────────────────────────────────────────────────────────────┐
│ task_id │ status │ command │
├─────────┼─────────┼───────────────────────────────────────────────────────────────────────────────────────────────┤
│ 52 │ blocked │ SELECT pg_catalog.citus_move_shard_placement(102049,'wdb1.host',5432,'wdb3.host',5432,'auto') │
│ 51 │ running │ SELECT pg_catalog.citus_move_shard_placement(102047,'wdb2.host',5432,'wdb4.host',5432,'auto') │
│ 50 │ done │ SELECT pg_catalog.citus_move_shard_placement(102048,'wdb1.host',5432,'wdb4.host',5432,'auto') │
│ 49 │ done │ SELECT pg_catalog.citus_move_shard_placement(102046,'wdb2.host',5432,'wdb3.host',5432,'auto') │
└─────────┴─────────┴───────────────────────────────────────────────────────────────────────────────────────────────┘
-- wait for a job to finish
select citus_job_wait(6);
-- cancel an ongoing job
select citus_job_cancel(6);
如果您更喜欢现有的行为(例如,您有一个依赖于重新平衡完成的脚本),您也可以继续使用现有的rebalance_table_shards函数。
除了在后台重新平衡之外,我们还进行了一些显着的性能和可靠性改进,以提供更好的重新平衡器体验。
PostgreSQL 15 (beta 4) 支持
使用 Citus,您可以获得一个分布式数据库,它允许您在任何规模上使用 PostgreSQL 的功能丰富、经过实战考验的功能集。更重要的是,当一个包含新改进的新 PostgreSQL 版本发布时,我们会立即将它们带给您。
PostgreSQL 15 即将到来,我们已经确保 Citus 11.1 能够与最新的 beta 4 版本一起顺利运行。一旦 PostgreSQL 15 GA 发布,我们将立即在 Citus 的补丁版本中添加全面支持。
在11.1 更新页面上,您可以找到分布式表支持哪些 PostgreSQL 15 功能的详细信息。
所有规模,无需停机
拥有非常大的数据库的主要挑战之一是某些操作可能需要很长时间。当此类操作阻止您的某些 Postgres 写入时,它们可能会中断您的应用程序几个小时,因此最好避免它们。Citus 11.1 通过让您在继续接受写入的同时分发表、拆分分片组和隔离租户,为您管理大型(和小型!)数据库提供了更大的灵活性。此外,您可以在后台在线重新平衡您的 Citus 数据库集群,而无需等待。
我们期待看到您将使用 Citus 11.1 和 PostgreSQL 15 构建的内容。您可以了解更多信息,加星 ⭐ 以表示您的支持,或在Citus GitHub存储库上提交您遇到的任何问题。如果您在 Azure 上使用 Citus,请知道我们的团队已经在努力让 Citus 11.1尽快在Azure 托管服务上可用。
如果您刚刚开始使用 Citus,这里有一些资源可以帮助您开始分发 Postgres!
原文标题:Citus 11.1 shards your Postgres tables without interruption
原文作者:Marco Slot
原文地址:https://www.citusdata.com/blog/2022/09/19/citus-11-1-shards-postgres-tables-without-interruption/




