PostgreSQL高可用之流复制架构
Whoami:5年+金融、政府、医疗领域工作经验的DBA
Certificate:OCP、PCP
Skill:Oracle、Mysql、PostgreSQL
Platform:CSDN、墨天伦、公众号(呆呆的私房菜)
业务范围:数据库安装部署、日常维护、主备切换、故障处理、性能优化、技术培训等。
需要的伙伴或者商业合作请移步 公众号【呆呆的私房菜】获取联系方式。
阅读本文可以了解到流复制概念和实现原理、优势、同步和异步主备流复制及其切换等相关内容。
01 流复制概念
流复制是一种高可用性和可伸缩性的解决方案。它允许将数据从一个PostgreSQL主数据库复制到一个或多个从数据库。它的工作原理是主服务器上能够持续地将数据变更发送到一个或多个从服务器上,这些从服务器接收到变更后会应用相同的变更以保持与主服务器的数据同步。
- 主服务器启动wal sender进程发送wal日志流;
- 从服务器通过wal receiver进程接收来自主库的wal日志;
- 从服务器调用内部函数write()和fsync()将wal数据全部写入wal segment和刷新到wal segment;
- 从服务器通过startup进程回放写入wal segment的wal日志读取和应用wal日志。

02 流复制分类
- 异步流复制:主服务器在事务提交时不需要等待从服务器的确认,事务可以立即完成;适用于对性能要求较高,可以容忍一定程度的数据延迟的场景。
- 同步流复制:主服务器在事务提交时会等待同步从服务器确认已经接收并写入相应的wal日志到磁盘;适用于对数据一致性要求极强的场景,但会牺牲一些性能。
03 流复制优势
- 实时性:流复制可以接近实时的数据复制;
- 数据一致性:同步流复制可以确保主从服务器的一致性;
- 高可用性:主服务器故障时,可以快速提升从服务器为主库;
- 读写分离:从服务器允许只读查询,减少主库压力。
04 流复制配置
异步流复制
bash
一、主库配置
# 调整配置文件
vi $PGDATA/postgresql.conf
# 表示日志记录级别
wal_level=replica
# 表示主库最多可以有多少个并发的standby
max_wal_senders=2
# 设置wal允许保留的总大小
wal_keep_size=1024MB
hot_standby=on
# 创建同步用户
create role repl login replication password 'repl';
# 调整连接白名单
vi $PGDATA/pg_hba.conf
host replication repl 192.168.56.0/24 md5
二、从库配置
# 清空从库数据目录
rm -rf $PGDATA/*
# 生成基础备份
pg_basebackup -h 192.168.56.6 -U repl -Fp -x -P -R -D $PGDATA -l repl_`date +'%Y-%M-%d'`.log
# 编辑从库配置文件
vi $PGDATA/postgresql.conf
# 配置从库允许访问
hot_standby=on
# 启动从库
pg_ctl start -D $PGDATA
三、查看主从同步状态
# 主库查看同步状态
select * from pg_stat_replication;
# 从库查看同步状态
select * from pg_stat_wal_receiver;
# 注意:
备库recovery.conf文件用于主备库切换时的参数配置;
可以从$PGHOME/share/recovery.conf.sample复制一份到备库$PGDATA目录;
也可以通过pg_basebackup指定-R参数,自动生成了该文件。
同步流复制
ini
一、主库配置
# 调整配置文件
vi $PGDATA/postgresql.conf
# 表示日志记录级别
wal_level=replica
# 表示主库最多可以有多少个并发的standby
max_wal_senders=2
# 设置wal允许保留的总大小
wal_keep_size=1024MB
hot_standby=on
# 指定多个standby名称,standby名称是在备库连接主库时,由连接参数application_name决定的
synchronous_standby_names='standby01,standby02'
# 创建同步用户
create role repl login replication password 'repl';
# 调整连接白名单
vi $PGDATA/pg_hba.conf
host replication repl 192.168.56.0/24 md5
二、从库配置
# 清空从库数据目录
rm -rf $PGDATA/*
# 生成基础备份
pg_basebackup -h 192.168.56.6 -U repl -Fp -x -P -R -D $PGDATA -l repl_`date +'%Y-%M-%d'`.log
# 编辑从库配置文件
vi $PGDATA/postgresql.conf
# 配置从库允许访问
hot_standby=on
# 启动从库
pg_ctl start -D $PGDATA
三、查看主从同步状态
# 主库查看同步状态
select * from pg_stat_replication;
# 从库查看同步状态
select * from pg_stat_wal_receiver;
# 注意:
备库的recovery.conf里的primary_conninfo一定要指定连接参数"application_name"
会话级别同步复制切换
主库已经配置参数synchronous_standby_names时(必要条件),会话执行 set synchronous_commit=off 可以在当前会话取消同步复制,改为异步复制。
05 流复制主备切换
主节点数据库服务异常的时候,可以手动把从节点切换成主节点,步骤如下:
- 关闭主库
arduino
pg_ctl stop -D $PGDATA -m fast
- 备库提升成主库
bash
pg_ctl promote -D $PGDATA
- 创建或修改原主库的recovery.conf文件,指向新主库
ini
recovery_target_timeline = 'latest'
standby_mode = 'on'
primary_conninfo = 'user=repl password=repl host=192.168.56.6 port=5432 sslmode=disable sslcompression=1'
- 启动原主库,检查状态是否正常
bash
pg_ctl start -D $PGDATA
06 流复制备库修复
主备不同步可以通过pg_rewind工具来进行修复;
PostgreSQL 9.5 版本将pg_rewind加入到源码中,当主备发生切换时,可以将原主库通过同步模式恢复,避免重做备库。这样针对较大的库来说,可以大量节省重做备库的时间;
pg_rewind工作原理是将目标端的数据文件、配置文件复制到本地目录,由于pg_rewind不会读取所有未发生变化的块,所以速度比重做备库要快很多。
pg_rewind检查源端与目标端的时间线历史来检测它们产生分歧的点,并在目标端的pg_wal日志中找到对应的wal去做修复。
ini
使用 pg_rewind 前提条件:
1. wal_log_hints = on
2. 初始化数据库时启用checksums功能
pg_rewind工作原理:
- 从最后一个检查点开始扫描老集群的wal日志,在该检查点之前,新集群的时间线历史从老集群被创建出来。对于每一个wal记录,做一个数据块被触及的记录。在新的集群被创建出来以后,这产生所有在老集群中被更改的数据块的列表;
- 从新集群复制所有这些被更改的数据块到老集群;
- 从新集群复制所有其它像clog,conf这样的文件等等到老集群。每个文件,除了表文件;
- 从新集群应用WAL,从故障转移创建的检查点开始。(严格的说,pg_rewind不应用wal,它只是创建一个备份标签文件以表明PostgreSQL被启动了,它会从检查点重放并应用所有需要的WAL)
ini
# 主备库时间线不一致时,可以通过rewind命令对齐时间线
pg_rewind --target-pgdata $PGDATA --source-server='host=192.168.56.7 port=5432 user=postgres dbname=postgres' -P
合集: PostgreSQL