暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Citus 11.1 不中断的对 Postgres 表进行分片

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 中更改的全部详细信息,请查看我们的更新页面。另请查看这篇博文的末尾,了解即将到来的Citus 11.1 发布直播的详细信息,其中将包括 3 个现场演示。


使用 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,create_distributed_table_concurrently建立在逻辑复制之上,将数据复制期间发生的写入发送到正确的分片中。

图 2:运行示例create_distributed_table_concurrently。应用程序可以在表分发时继续写入表,最后只看到一个短暂的延迟。

在不阻塞写入的情况下跨集群分布表是一个非常神奇的过程,但要记住一些限制:

  • 如果您的表上没有primary key/replica identity,则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 中,相同的函数变成了允许写入持续到结束操作:

--将租户293隔离到自己的分片组中
select isolate_tenant_to_new_shard('observations', 293);

图 3:具有大租户的数据库导致分片大小倾斜。我们在继续查询(包括写入)时隔离此租户。

操作完成后,原始分片被拆分为 3 个,以便在集群中更好地平衡。
租户隔离操作后,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 个节点上。当您超出此限制时,最好有一种方法来拆分分片而无需停机:

-- 在节点2和节点3上将分片102008所属的分片组拆分为两段:

-- (参见pg_dist_node编目表中的nodeid列)

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_shardwhere shardid = 102008; /* shard to split (along with all co-located shards) */

当单个分片组开始超过单个节点时,拆分分片的能力也可以成为救命稻草。未来,我们计划为分片拆分提供更方便、自动化的API,目前拥有的底层功能已经可以在紧急情况下提供帮助。分片拆分建立在逻辑复制之上。

当逻辑复制处于活动状态时,如果没有REPLICA IDENTITY(例如主键),更新/删除查询将失败。默认情况下,如果要拆分的表之一没有REPLICA IDENTITY,则拆分和隔离函数会引发错误,以防止意外停机。好消息是,没有主键的表类型通常不是经常更新的表类型。

您可以通过传递参数shard_transfer_mode := 'force_logical'允许拆分继续进行逻辑复制。您还可以通过shard_transfer_mode := 'block_writes' 在拆分期间阻止所有写入,这会跳过逻辑复制步骤并且可以更快一些。

我们将在以后的博客文章中分享更多关于如何使逻辑复制适用于分片拆分的详细信息。


在后台更快地重新平衡分片

横向扩展 Citus 数据库集群传统上是一个两步过程:

1)向 Citus 集群添加新节点;

2)通过调用 SQL 函数rebalance_table_shards()重新平衡分片。

重新平衡使用逻辑复制在节点之间移动分片组以避免阻塞写入。
我们要求您单独进行重新平衡有几个原因。其中之一是防止某些表没有主键并且设置逻辑复制会导致更新/删除失败的情况。另一个原因是您可能希望在一天中较安静的时间重新平衡,以确保它不会与峰值负载竞争资源。

到目前为止,重新平衡的一个更烦人的方面是rebalance_table_shards功能可能需要很长时间才能完成,并且您必须始终保持 PostgreSQL 连接打开,并检查是否有故障,这在长时间运行的数据移动期间偶尔会发生。幸运的是,Citus 11.1 引入了一种运行分片重新平衡器的新方法,该方法将单个分片移动放置在专用的后台作业队列中,让您一劳永逸。

当您在 11.1 中调用新citus_rebalance_start函数时,会安排一个重新平衡作业,该作业可以包含多个分片组移动任务,以使集群进入平衡状态。每次移动都会重试几次以防失败,您可以在任务队列中跟踪进度,并轻松取消作业。

--启动一个rebalance作业,立即完成并返回作业ID

SELECT citus_rebalance_start();

┌───────────────────────┐
│ citus_rebalance_start │
├───────────────────────┤
│                     6 │
└───────────────────────┘
(1 row)

--查看作业状态
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)

-- 检查单个移动任务

-- (阻塞的任务正在等待正在运行的移动)    

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') │└─────────┴─────────┴───────────────────────────────────────────────────────────────────────────────────────────────┘
``

-- 等待作业完成

select citus_job_wait(6);

--取消正在进行的作业

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!

下载页面:https://www.citusdata.com/download/

Citus 文档:https://docs.citusdata.com/en/v11.1/

入门页面:https://www.citusdata.com/getting-started/

有一组精心策划的有用链接,指向文档、视频、博客等开源部分,以及Citus在云中的托管服务。

点击此处阅读原文
文章转载自开源软件联盟PostgreSQL分会,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论