介绍
在这篇博客中,我们将讨论 Postgres 16 中新增的一些更高级的特性。假设您拥有一些 Linux、Postgres 和 SQL 的经验,因为我们不仅要讨论这些新功能,还要讨论如何实现它们。本博客是使用在 Ubuntu 23.04 上运行的 PostgreSQL 16(开发版本)编写的。首先,我将回顾一些背景知识并简要介绍什么是双向复制以及为什么它很重要,然后结束我们如何实现双向逻辑复制。
背景
在开始学习双向逻辑复制之前,我们首先必须了解逻辑复制。
逻辑复制基础知识
逻辑复制从 PostgreSQL 10 开始就得到支持,并在接下来的几年中得到了许多更新和改进。逻辑复制是将复制 表示为数据对象变更事件流。通过这种方式,我们可以仅复制表等对象的特定变更,而不是整个数据库,并跨不同平台和版本流式传输这些变更 。这与物理复制形成鲜明对比,物理复制使用精确的块地址,因此仅限于复制整个数据库,并且不能跨平台或版本进行流式传输,因为数据必须在两者中匹配。
图 1:逻辑复制架构概述
逻辑复制还引入了实现 双向副本(Bi-Directional ) 所必需的两个非常重要的元素。它们是发布者和订阅者,你可以将它们视为领导者节点(发布者)和追随者节点(订阅者)。发布者将收集其最近的变更并将它们作为命令的有序列表发送给订阅者。一旦接收到,订阅者就会接受这一系列命令并将其应用于其数据。如果两个数据库都以相同的数据开始,则订阅服务器将与发布服务器保持同步。
双向复制
既然我们了解了逻辑复制是什么,那么双向复制有何不同之处呢?简而言之,双向逻辑复制是指复制中的所有节点既是发布者又是订阅者。现在,每个数据库都可以处理读取和写入请求,并且所有更改都将相互传输。这是双向的,因为变化不再像以前那样朝一个方向流动,而是朝两个方向流动。
图 2:双向复制架构概述
Postgres 16 添加了一个 WITH 语句的新参数,用于过滤掉某些节点的复制。双向逻辑复制使用此参数WITH(ORIGIN = NONE),这会过滤掉来自非NONE 源的连接的所有复制。本质上,这只允许复制新添加的数据,您可能会明白为什么会出现这种情况。如果一个数据库插入新数据并将其复制到第二个数据库,则第二个数据库将复制该数据并插入它,从而触发对原始数据库的另一次复制。我们很快就会得到无限的复制循环,这就是为什么这个选项对于保持一切有限是必要的。
好处
双向逻辑复制的主要好处是,由于我们有两个主节点,因此它可以为读取和写入请求提供更高的可用性。这对于特别需要写入的各种应用程序来说非常有益。
缺点
双向逻辑复制需要一些先决条件才能正确运行,因为它的许多缺点都来自这些特定条件。例如,在设置复制时,每个数据库中的表必须遵循相同的架构。相同的名称和列,否则订阅者将无法找到该表。在逻辑复制可以支持用于创建表的数据定义语言 (DDL) 的复制之前,用户必须手动执行此操作以确保一致性。
配置
现在我们了解了双向逻辑复制的基础知识,我们可以研究如何在两个数据库之间实现它。一开始与设置常规逻辑复制非常相似,但在创建发布者和订阅者时有一个非常重要的区别。
首先,我们将创建两个相互跟随的主数据库:
sql
$ initdb -D database1
$ initdb -D database2
在每个数据库的 postgres.conf 文件中,将每个数据库的 way_level 设置为逻辑级别,并为每个数据库指定一个唯一的端口号:
database1 的 postgres.conf配置
ini
port = 5432
wal_level = logical
database2 的 postgres.conf 配置
ini
port = 5433
wal_level = logical
启动两个数据库:
sql
pg_ctl -D database1 -l database1.log start
pg_ctl -D database2 -l database2.log start
为每个数据库创建发布者:
sql
CREATE PUBLICATION mypub1 FOR TABLE mytable;
CREATE PUBLICATION mypub2 FOR TABLE mytable;
为每个数据库创建订阅者:
sql
CREATE SUBSCRIPTION mysub1 CONNECTION 'host=127.0.0.1 port=5433 user=postgres dbname=postgres' PUBLICATION mypub2 WITH(ORIGIN = NONE);
CREATE SUBSCRIPTION mysub2 CONNECTION 'host=127.0.0.1 port=5432 user=postgres dbname=postgres' PUBLICATION mypub1 WITH(ORIGIN = NONE);
请注意我们创建发布者和订阅者的顺序 ,首先创建发布者然后创建订阅者非常重要。如果您想要更直观的表示,可以参考图 2,每个组件 角上的数字表示它们的创建顺序。
现在,当任何数据插入任一数据库时,都应该在两个节点之间复制。
结论
在本博客中,我们回顾了 PostgreSQL 16 中新的双向逻辑复制功能。首先,我们回顾了逻辑复制和用于同步数据的发布者/订阅者模型的简要背景。然后,我们了解了双向逻辑复制的工作原理以及允许其在不触发无限复制循环的情况下运行的新参数。最后,我们研究了如何使用两个主 PostgreSQL 数据库设置双向复制。通过支持主节点之间的同步,对于任何数据库应用程序来说,提高可用性和数据持久性都应该变得轻而易举。
References 参考 C, Vigneshwaran. Bi-Directional Replication Using Origin Filtering in PostgreSQL, Fujitsu, 31 Aug. 2023,. C、维涅什瓦兰。在 PostgreSQL 中使用源过滤的双向复制,富士通,2023 年 8 月 31 日