一、什么是流复制

PostgreSQL的流复制是什么?

简单:通过wal日志来进行数据同步之类的

更准确一些:

PostgreSQL通过wal日志来传送的方式有两种:基于文件的日志传送和流复制 所以流复制不同于基于文件的日志传送,流复制的关键在于“流”,所谓流,就是没有界限的一串数据,类似于 河里的水流,是连成一片的。因此流复制允许一台后备服务器比使用基于文件的日志传送更能保持为最新的状 态。 比如我们有一个大文件要从本地主机发送到远程主机,如果是按照“流”接收到的话,我们可以一边接收,一边 将文本流存入文件系统。这样,等到“流”接收完了,硬盘写入操作也已经完成

1.1 流复制发展

pg在流复制出现之前,使用的就是基于文件的日志传送:对wal日志进行拷贝,因此从库始终落后主库一个日 志文件,并且使用rsync工具同步data目录

pg9在2010年推出了流复制

  • 起源:pg9.0开始支持流式物理复制,用户可以通过流式复制,构建只读备库 (主备物理复制,块级别一致)。流式物理复制可以做到极低的延迟(通常在1毫秒以内)。

  • 同步流复制:pg9.1开始支持同步复制,但是当时只支持一个同步流复制备节点(例如配置了3个备,只有 一个是同步模式的,其他都是异步模式)。同步流复制的出现,保证了数据的0丢失。

  • 级联流复制:pg9.2支持级联流复制。即备库还可以再连备库。

  • 流式虚拟备库:pg9.2还支持虚拟备库,即就是只有WAL,没有数据文件的备库。

  • 逻辑复制:pg9.4开始可以实现逻辑复制,逻辑复制可以做到对主库的部分复制,例如表级复制,而不是 整个集群的块级一致复制。

  • 增加多种同步级别:pg9.6版本开始可以通过synchronous_commit参数,来配置事务的同步级别

所以总结一下:

流复制其原理为:备库不断的从主库同步相应的数据,并在备库apply每个WAL record,这里的流复制每次传 输单位是WAL日志的record。

PostgreSQL物理流复制按照同步方式分为两类:

  • 异步流复制

  • 同步流复制

物理流复制具有以下特点:

1、延迟极低,不怕大事务

2、支持断点续传

3、支持多副本

4、配置简单

5、备库与主库物理完全一致,并支持只读

流复制和逻辑复制的对比:

  • 流复制只能对postgresql实例级进行复制,不能单独对某个库或者某个表复制(而逻辑复制能够对数据库 表级进行复制)

  • 流复制能 DDL 操作进行复制,比如主库上新建表、给已有表减字段时会自动同步到备库,(逻辑复制主 库上的 DDl 操作不会复制到备库)

  • 流复制主库可读写,但从库只允许查询不允许写人, 逻辑复制的从库可读写

  • 流复制要求 PostgreSQL 大版本必须一致,逻辑复制支持跨 PostgreSQL 大版本

二、重提wal日志

对数据库操作会以record为单位首先记录到wal日志中,在checkpoint时才对数据进行刷 盘(background writer会定时刷脏数据,但最终还是都由checkpoint确认都刷盘成功)

查看当前的流式复制的wal日志

select pg_walfile_NAME_OFFSET(pg_current_wal_lsn());

三、流复制原理

3.1 日志提交过程

流复制中日志提交的大致流程为:

1、事务commit后,日志在主库写入wal日志,还需要根据配置的日志同步级别,等待从库反馈的接收结 果。

2、主库通过日志传输进程将日志块传给从库,从库接收进程收到日志开始回放,最终保证主从数据一致 性。

3.2 流复制同步级别

PostgreSQL通过配置synchronous_commit (enum)参数来指定事务的同步级别。我们可以根据实际的业务需 求,对不同的事务,设置不同的同步级别

synchronous_commit = off

可选:# off, local, remote_write, or on

  • remote_apply:事务commit或rollback时,等待其redo在primary、以及同步standby(s)已持久化,并且 其redo在同步standby(s)已apply。

  • on:事务commit或rollback时,等待其redo在primary、以及同步standby(s)已持久化。

  • remote_write:事务commit或rollback时,等待其redo在primary已持久化;其redo在同步standby(s)已调 用write接口(写到 OS,但是还没有调用持久化接口如fsync)。

  • local:事务commit或rollback时,等待其redo在primary已持久化;

  • off:事务commit或rollback时,等待其redo在primary已写入wal buffer,不需要等待其持久化;

不同的事务同步级别对应的数据安全级别越高,对应的对性能影响也就越大。上述从上至下安全级别越来越低

3.3 异步流复制

流复制根据数据通步方式分为异步流复制和同步流复制,

什么异步流复? 是指主库上提交事务不需要等待备库接WAL志流并写入备库WAL志文件时便返回 而同步流复制刚好相反

3.4 同步流复制

同步流复制在主库上提交事务时需等待备库接收并 WAL ,当主库至少收到一个备库发回的确认信息时便返回 成功,同步流复制确保了至少一个备库收到了主库发送的 WAL日志,一方面保障了数据的完整性,另一方面增 加了事务响应时间,因此同步流复制时,主库的吞吐量相比异步流复 主库吞吐量要偏低 大概10%-20%

3.5 怎么配置同步流复制

备库recovery.auto.conf
primary_conninfo= 'host=l92.168.28.7 4 port=5432 user=repuser application_name='node1'

主库
synchronous_commit = on 或者 remote_apply
synchronous_standby_name = 'node1'

3.6 同步流复制的典型的“陷阱”

同步流复制模式中,由于主库提交事务时需等待至少一个备库接收 WAL 并返回确认信

息后主库才 客户端返回成功, 方面保障了数据的完整性,另一方面对于一主一备的同 步流复制环境存在一个典型的“陷阱”,具体表现为如果备库若机,主库上的写操作将处于等待状态导致卡住

所以:

通常生产上一主一备情况下不会采用同 步复制方式,因为备库若机后同样对生产 统造成严重影响

3.7 流复制的配置注意事项

3.7.1 wal_level

参数控 WAL 日志信息的输出级别,有 minimal replica logical模式

  • minimal 记录WAL志信息最少,除了记录数据库异常关闭需要恢复时的 WAL 信息外,其他操作信息都不 记录

  • replica WAL 信息比 minimal 信息多些,会记录支持 WAL 档、复制和备库中启用只读等操作所需的 WAL 信息;

  • logical WAL日志最多, 包含了支持逻辑解析 (1O 版本的新特性,逻辑制)所 WAL ; replica 模式 录的 WAL minimal 的信息, logical 模式记录的 WAL 信息包含了replica 记录的信息,

参数默认值为 replica ,调整参数需重启数据库生效,开启流 制至少需要设置 参数为 replica 级别

3.7.2 archive_mode

控制是否启用归档, off 表示不启用归档, on 表示启用归档并使archive command 参数的配 命令将 WAL 日 志归档到归档存储上,此参数设置

后需重启数据库生效,这里通常常设置成 on

3.7.3 archive_command

参数设置 WAL 归档命令, 可以将 WAL归档到本机目录,也可以

归档到远程 机上,但是流复制的配置并不一 需要依赖配置归档命令,建议尽量设置

3.7.4 max_wal_senders

参数控制主库上的最大 WAL 发送进程数 ,通过 pg_basebackup 命令在主库上做基准备份时也会消耗 WAL进 程, 参数设置不能 max_connections 参数的最高值,默认值为 10 1个流 备库通常只需要消耗流复制主库 WAL

进程 ,所以如果有多个的话需要加大这个参数

wal_keep_segments

参数设置主库pg_wal目录保留的最小 wal 日志文件数,以便备库落后主库时可以通过主库保留的 WAL 进行追 回,这个参数设置得越大,理论 上备库在异常断开时追平主库的机率越大,如果归档存储空间充足,建议将此参数配置得大些,由于默认情况 下每个 WAL 文件为 16MB ,因此 pg_wal 目录大概占用空间大概 wal_keep_

segments 参数值× 16MB ,比如设置为512,那么就是 512*16MB=8GB ,所以一般建议设置大一些 比如 1024 或者2048

3.7.5 hot_standby

参数控制数据库恢复过程中是否启用读操作 ,这个参数通常用在流复制备库,开启此参数后流复制备库支持只 读 SQL,但备库不支持写操作,主库上也设置

参数为 on

3.7.6 pg_hba.conf

pg_hba.conf 之前说过主要是控制访问pg的黑白名单,在配置流复制时需要加上如下,添加以下内容:

host replcation repuser 0.0.0.0 md5

3.7.7 流复制账号

一般建议专门为流复制建立一个账号,比如:

CREATE USER rep
REPLICATION
LOGIN
CONNECTION LIMIT 5 ENCRYPTED PASSWORD 'rep123';

或者

CREATE USER rep with replication;
ALTER USER rep WITH PASSWORD 'rep123';
ALTER USER rep WITH LOGIN;
ALTER USER rep WITH SUPERUSER 主要是防止如果用这个用户去查询一下复制表信息会报错