pg流复制详解

本文涉及的产品
日志服务 SLS,月写入数据量 50GB 1个月
云原生数据库 PolarDB MySQL 版,通用型 2核4GB 50GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
简介: pg流复制详解

pg_replication

基本概念

  • 逻辑复制
    逻辑复制是将数据重新执行一次insert、update或delete。逻辑复制则允许在数据层面复制,并在安全性上提供更细粒度的控制。
  • 流复制(物理复制)
    实现方式是将wal日志中记录的内容按照确切的块地址逐字节的拷贝到备库,因此主备之间数据分布是一致的,这意味着在主备机器上,同一条记录的ctid是相同的。
  • 逻辑解码
    逻辑解码是提取数据库表的所有永久修改到一个连贯的、容易理解的格式 (不需要详细的数据库内部状态知识就可以解读)的过程。
  • 复制槽
    在逻辑复制的概念中,一个槽代表一连串的修改,这些修改可以以它们在原始服务器上制作的顺序在客户端上重放。
  • 输出插件
    输出插件将数据从预写式日志的内部表示转换到复制槽想要的消费者的格式。
  • 导出快照
    当用流复制接口创建了一个新的复制槽时,pg会导出一个快照, 该快照将准确的显示数据库的状态,之后所有的修改都将包含在修改流中。这可以用来创建一个新的复制品, 可以通过使用SET TRANSACTION SNAPSHOT 读取槽创建瞬间数据库的状态。这个事务稍后可以用来转储在那个时间点的数据库状态, 之后可以使用槽的内容更新该数据库而不丢失任何修改。

逻辑复制

逻辑解码

逻辑解码基本原理是从 WAL日志解码,跟踪所有 DML (INSERT, UPDATE, DELETE)更改。之后转换成各种可用的格式,比如 Json。

其流程大致如下:

insert/update/delete

postgresql

wal日志

logical_decoding

replication_slot

wal2json

jsonoutput

对于逻辑解码插件,主要有以下几类。按照格式来分主要有

  • JSON format plugins
  • Protobuf Format Plugins
  • Avro Format Plugins
  • SQL Format Plugins
  • Miscellaneous Plugins

参数配置

逻辑解码参数配置如下:

wal_level=logical

max_replication_slots=10

max_wal_sender=10

  • wal_level设置为logical允许WAL记录逻辑解码所需的信息。
  • max_replication_slots指定了发送端可以支持的最大复制槽数量,默认为10个
  • max_wal_sender指定发送方用于流复制的并发连接的最大数量,默认值也是10

pg_recvlogica

pg_recvlogical是 PostgreSQL自带的工具,它管理插槽并使用插槽中的流数据。

必须至少要指定下列选项之一来选择一个动作:

  • --create-slot
    --dbname指定的数据库用--slot 指定的名称创建一个新的逻辑复制槽,使用 --plugin指定的输出插件。
  • --drop-slot
    删除名称由--slot指定的复制槽,然后退出。
  • --start
    --slot指定的逻辑复制槽开始进行流式传送更改,一直继续 到被一个信号终止。如果服务器端关机或者断开连接导致更改流结束,会进入一个 循环一直重试,通过指定--no-loop可以防止这种情况下进入 循环重试。流格式由槽创建时指定的输出插件决定。连接必须是连接到用于创建该槽的同一个数据库上。

--create-slot--start可以被一起指定。 --drop-slot不能和另一个动作组合在一起。

物理流复制

物理流复制内容主要引用自博客

物理流复制是一种数据库主备同步技术,该特性同步的数据是数据库中物理页面变化数据(WAL),该模式备库的底层数据页面状态和主库完全相同,这样的实现方案让数据库主备以及同步状态都非常稳定。

流复制中的角色

  • 主库 backend 进程
    它负责执行用户的 SQL,在修改数据前会先记录 WAL(Write-Ahead Logging)日志。这些日志中事物提交日志(CommitTransaction)由 backend 进程负责写到磁盘。
  • 主库 WALsender 进程
    负责把 WAL 日志发送给备库的 WALreceiver 进程。
  • 备库 WALreceiver 进程
    负责接收 WALsender 发送的 WAL 日志,并持久化到存储。
  • 备库 startup 进程
    负责恢复 WALsender 写到磁盘上的 WAL 日志,把数据 apply 到数据页面上。

异步流复制

默认状态下的流复制是以异步方式工作的,也就是说主库写本地数据和 WAL 日志,WALsender 异步的把数据发送给备库,备库收到数据后再异步的做数据恢复。

异步模式可以做到较好的性能,它的劣势是:极端情况下,主库如果当机,被库被激活成主库,部分 WAL 没有发送到备库,可能造成数据丢失。

同步流复制

相对于异步模式,PostgreSQL 还支持同步模式的流复制。同模模式可以细分为三级

  • REMOTE_WRITE
    保证该事务的所有数据被备库收到(备库收到数据并调用 write 写磁盘,但并未持久化到磁盘)
  • REMOTE_FLUSH
    保证该事务的所有数据在备库持久化到磁盘(调用 flush,但只读查询看不到)
  • REMOTE_APPLY
    保证该事务的所有数据在备库被恢复到数据页面(恢复进程读取并解析 WAL,再 APPLY 到数据页面,在备库上执行的只读查询能看到数据的变化)

源码解析

简单的说 PostgreSQL ACID 是基于 MVCC 和 WAL 技术。数据的修改过程可以简单描述为:

  • 首先 backend 开启是一个事务,获得一个事务号 XID;
  • 在这个事务中对数据的任意修改,都被 XID 标记。
  • 其他 backend 在扫描数据时,会看到被这个 XID 修改过的数据,根据当前的隔离级别,选择对这些数据是否可见(默认的读已提交隔离级别看不到这些数据)。
  • 只有当此 XID 最后被标记成 commit (写 WAL commit log 和写 clog)后,其他的 backend 才能看到这个 XID 修改的数据。

实现流复制的同步模式,关键点在每个事务提交或回滚时,保证它产生的所有数据变化日志,即 WAL 都“同步”到备库。最后一条 WAL commit log 尤为关键。

  1. [主库 backend 进程]调用 RecordTransactionCommit 中写 WAL commit log,获得这条日志在在 WAL 中的位置 XLogRecPtr
  2. [主库 backend 进程]完成写 WAL 后,进入 SyncRepWaitForLSN 等待 WAL 日志“同步”到备库。具体做法是:在共享内存中创建一个等待队列 SHMQueue 记录 XLogRecPtr,并调动 WaitLatch,让出 CPU 等待被唤醒。
  3. [主库 WALsender 进程]相应所有备库的 WALreceiver 拉取 WAL 的请求。把 WAL 发送给所有备库。
  4. [备库 WALreceiver 进程]写 WAL 的偏移(LogstreamResult.Write)和持久化 WAL 偏移(LogstreamResult.Flush)记录下来。
  5. [备库 startup 进程]不断的恢复数据,把当前恢复到的 WAL 位点放在共享内存 xlogctl->lastReplayedEndRecPtr 中。
  6. [备库 WALreceiver 进程]不断通过 r 报文和主库 WALsender 进程同步的状态,即 XLOG_WRITE_LSN XLOG_REMOTE_LSN XLOG_APPLY_LSN(XLogWalRcvSendReply)
  7. [主库 WALsender 进程]收到备库发送的 r 报文后,检查共享内存中的等待队列 SHMQueue, 根据备库反馈的位点结合 SHMQueue,唤醒那些等待队列中睡眠的 主库 backend 进程(WalSndWaitForWal)。
  8. [主库 backend 进程]被唤醒,当前事务成功提交,SQL 执行完成返回给客户端。
  • 事务写入流程
  • CommitTransactionCommand
  • CommitTransaction
  • RecordTransactionCommit
  • BufmgrCommit
  • XactLogCommitRecord
  • SyncRepWaitForLSN
  • WalSender
    WalSender是Wal日志发送进程,运行在主库。当收到备库的WalReciver进程发过来的建链请求时,主库postgres进程会fork出WalSender进程。
  • BackendStartup
  • BackendRun
  • PostgresMain
  • InitWalSender
  • exec_replication_command
  • StartReplication
  • WalSndLoop
  • XLogSendPhysical
  • StartLogicalReplication
  • XLogSendLogical

switch (cmd_node->type)

   {

       caseT_IdentifySystemCmd:

           IdentifySystem();

           break;

       caseT_ReadReplicationSlotCmd:

           ReadReplicationSlot((ReadReplicationSlotCmd*) cmd_node);

           break;

       caseT_BaseBackupCmd:

           SendBaseBackup((BaseBackupCmd*) cmd_node);

           break;

       caseT_CreateReplicationSlotCmd:

           CreateReplicationSlot((CreateReplicationSlotCmd*) cmd_node);

           break;

       caseT_DropReplicationSlotCmd:

           DropReplicationSlot((DropReplicationSlotCmd*) cmd_node);

           break;

       caseT_StartReplicationCmd:

           {

               StartReplicationCmd*cmd= (StartReplicationCmd*) cmd_node;

               if (cmd->kind==REPLICATION_KIND_PHYSICAL)

                   StartReplication(cmd);

               else

                   StartLogicalReplication(cmd);

               break;

           }

       caseT_TimeLineHistoryCmd:

           EndReplicationCommand(cmdtag);

           break;

       caseT_VariableShowStmt:

               CommitTransactionCommand();

           break;

       default:

           elog(ERROR, "unrecognized replication command node tag: %u",

                cmd_node->type);

   }

  • WalReciver
    从库启动时会在postgresql启动时就创建WalReciver进程,并主动连接主库。
  • main
  • PostmasterMain
  • StartChildProcess
  • fork_process
  • AuxiliaryProcessMain
  • WalReceiverMain

reference

  1. https://www.modb.pro/db/11333
  2. http://www.postgres.cn/docs/9.4/logicaldecoding-explanation.html
  3. https://www.modb.pro/db/48147
  4. https://www.modb.pro/db/90943
  5. http://mysql.taobao.org/monthly/2018/01/03/
相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
4月前
|
关系型数据库 数据库 PostgreSQL
[postgres]配置主从异步流复制
[postgres]配置主从异步流复制
|
监控 关系型数据库 API
PostgreSQL 13、14中逻辑复制/解码改进
PostgreSQL 13、14中逻辑复制/解码改进
251 0
|
关系型数据库 数据库 PostgreSQL
PostgreSQL 同步流复制原理和代码浅析
数据库ACID中的持久化如何实现 数据库ACID里面的D,持久化。 指的是对于用户来说提交的事务,数据是可靠的,即使数据库crash了,在硬件完好的情况下,也能恢复回来。PostgreSQL是怎么做到的呢,看一幅图,画得比较丑,凑合看吧。假设一个事务,对数据库做了一些操作,并且产生了一些脏数据,
13388 0
|
关系型数据库 Linux 数据库
PostgreSQL数据库异步的流复制
一、虚拟主机安装 1.使用VMware虚拟机安装CentOS操作系统操作系统环境CentOS Linux release 7.2.1511 (Core) 软件选择 选择安装GNOME桌面 安装位置 选择自动分区 2.通过克隆的方式,生成主备两台主机。
1895 0
|
关系型数据库 数据库 PostgreSQL
|
关系型数据库 流计算
|
Oracle 关系型数据库 数据库
|
SQL 监控 Oracle