PostgreSQL16中的新增功能:双向逻辑复制

LogicWaltzPro
• 阅读 405

在这篇博客中,我们将深入探讨Postgres 16中引入的一些更高级的新功能。为了更好地理解这些功能,读者应具备一些Linux、Postgres和SQL的基础知识,因为我们将深入探讨这些新功能并指导如何实现它们。

本博客以在Ubuntu 23.04上运行的PostgreSQL 16(开发版)为基础进行编写。首先,我们将介绍一些背景信息,并简要介绍什么是双向复制,以及为什么它很重要,然后介绍我们如何实现双向逻辑复制。

1 背景

在开始学习双向逻辑复制之前,我们首先必须了解什么是逻辑复制。

2 逻辑复制的基础知识

从 PostgreSQL 10 就支持逻辑复制功能,并且在接下来的几年中逻辑复制功能已得到广泛应用和持续更新。逻辑复制是复制 (ie. replicating)数据对象的过程,其表示为它们的更改。通过这种方式,我们可以只复制表等对象的特定更改,而不是复制整个数据库,并将这些更改流式传输到不同的平台和版本。与物理复制形成鲜明对比,逻辑复制更注重于抽象层面的数据表示,这使得它能在不同平台和版本之间实现无缝的数据流传输。相比之下,物理复制更依赖于确切的块地址,导致其复制范围局限于整个数据库,且无法跨平台或版本进行数据流传输,因为每个平台或版本的数据结构必须完全匹配。
PostgreSQL16中的新增功能:双向逻辑复制
图1

逻辑复制还引入了理解其双向对应关系所必不可少的两个非常重要的元素:发布者和订阅者,你可以将它们理解为领导者节点(发布者)和跟随者节点(订阅者)的角色。发布者将收集其最近的更改,并将其作为有序的命令列表发送到订阅者。一旦订阅者接收到这一系列命令,就会将其应用于其数据。如果两个数据库最初具有相同的数据,那么订阅者将与发布者保持同步。

3 双向复制现

在我们了解了什么是逻辑复制,那么双向复制有什么不同之处呢?简而言之,双向逻辑复制是指复制中的所有节点都同时充当发布者和订阅者。现在,每个数据库都可以处理读写请求,所有的更改都会以流式传输的方式传递给彼此。这就是双向的方面,与之前只有单向变化流动不同,现在变化在两个方向上都进行流动。 
PostgreSQL16中的新增功能:双向逻辑复制
图2

Postgres 16 新添加的地方是它向 WITH 语句添加了一个新参数,用于过滤掉来自特定节点的复制。双向逻辑复制使用此参数 WITH(ORIGIN = NONE),这会过滤掉所有具有非NONE起源的连接的复制。从本质上讲,这只允许复制新添加的数据,您或许可以看到为什么会这样。如果一个数据库插入新数据并将其复制到第二个数据库,则第二个数据库将复制数据并插入该数据,从而触发对原始数据库的另一次复制。我们很快就陷入到无限复制的循环中,这就是为什么需要这个选项来保持一切有限的原因。

4 好处

双向逻辑复制的主要优势在于,它提供了更多的可用性,既可以满足读请求,也可以满足写请求,因为我们有两个主节点。这对于许多需要强调写操作的应用程序来说尤其有益。

5 缺点

双向逻辑复制需要一些前提条件才能正常运行,因为它的许多缺点都来自这些特定条件。例如,在设置复制时,每个数据库中的表必须遵循相同的架构、相同的名称和列,否则订阅服务器将无法找到该表。在逻辑复制可以支持复制用于创建表的数据定义语言 (DDL) 之前,用户必须手动执行此操作以确保一致性。

6 建立

现在我们了解了双向逻辑复制的基础知识,我们可以深入研究如何在两个数据库之间实现它。开始与设置常规逻辑复制非常相似,但在创建发布服务器和订阅服务器时有一个非常重要的区别。

首先,我们将创建两个主数据库,它们将相互跟随:

$ initdb -D database1$ initdb -D database2

在每个数据库的 postgres.conf 文件中,将每个数据库的way_level设置为逻辑,并为每个数据库指定一个唯一的端口号:

postgres.conf 数据库1

port = 5432wal_level = logical

postgres.conf 数据库2

port = 5433wal_level = logical

启动两个数据库:

pg_ctl -D database1 -l database1.log startpg_ctl -D database2 -l database2.log start

为每个数据库创建发布服务器:

# CREATE PUBLICATION mypub1 FOR TABLE mytable;
# CREATE PUBLICATION mypub2 FOR TABLE mytable;

为每个数据库创建订阅服务器:

# 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。每个组件角落的数字表示它们的创建顺序,这有助于确保复制过程的顺利进行。

现在,当任何数据插入任一数据库时,都应在两个节点之间进行同步复制。

7 结论

在这篇博客中,我们介绍了 PostgreSQL 16 中的新双向逻辑复制功能。首先,我们简要介绍了逻辑复制的背景以及用于同步数据的发布者/订阅者模型。然后,我们讨论了双向逻辑复制的工作原理以及允许其在不触发无限复制循环的情况下运行的新参数。

最后,我们了解了如何在两个主PostgreSQL 数据库之间设置双向复制。通过支持主节点之间的同步,增加可用性和数据持久性对于任何数据库应用程序都应该是轻而易举的。

*参考文献:
C, Vigneshwaran. Bi-Directional Replication Using Origin Filtering in PostgreSQL, Fujitsu, 31 Aug. 2023, www.postgresql.fastware.com/blog/bi-directional-replication-using-origin-filtering-in-postgresql.

原文链接:
https://www.highgo.ca/2023/12/18/new-in-postgresql-16-bi-dire...

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Stella981 Stella981
3年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
LogicWaltzPro
LogicWaltzPro
Lv1
人有悲欢离合,月有阴晴圆缺,此事古难全。但愿人长久,千里共婵娟。
文章
3
粉丝
0
获赞
0