PostgreSQL 流复制配置环境搭建过程
作者:Bing@DBA
前言
PostgreSQL 流复制(Streaming Replication)是 9.0 提供的一种新的 WAL 传递方法。使用流复制时,每当 Primary 节点 WAL 产生,就会马上传递到 Standby 节点,流复制提供 异步
和 同步
两种模式,同步模式可以保障数据 0 丢失。
1. 配置环境
1.1 环境介绍
主机名 | IP 地址 | 角色 | 数据目录 |
---|---|---|---|
172-16-104-7 | 172.16.104.7 | Master | /data/pgsql12/data/ |
172-16-104-56 | 172.16.104.56 | Standby | /data/pgsql12/data/ |
PostgreSQL 版本:PostgreSQL 12.2操作系统:CentOS Linux release 7.8.2003 (Core)
1.2 主库白名单
Master 节点配置 pg_hba.conf
表示接受流复制的用户连接:
host replication all 0/0 md5
上面这条 SQL 语句的含义是允许任意用户从任何网络(0/0)网络上发起到本数据库的流复制连接,使用MD5的密码认证。
1.3 主库参数配置
# 监听 listen_addresses = '*' # 流复制客户端的最大并发数,设置为 0 表示禁用复制 max_wal_senders = 10 # WAL 日志级别 wal_level = replica
上面的参数需要重启 PostgreSQL 服务后生效。
2. 流复制搭建
使用 pg_basebackup 将主库数据备份恢复到 Standby 节点,搭建 异步/同步
流复制,步骤归纳:
- 准备环境 PostgreSQL 主节点和备节点。
- 参数调整 pg_hba.conf、postgresql.conf,创建复制用户。
- 备份主节点的数据,恢复到备节点。
- 修改 primary_conninfo 启动备库。
- 检查是否启动成功。
2.1 备份恢复
在主库执行全量备份:
pg_basebackup -D /data/pgsql12/backup -v -P -X stream -Upostgres -h 127.0.0.1 -p5432 -R
将备份 SCP 到备库节点:
scp -r ./backup/ root@172.16.104.56:/data/backup
关闭 Standby 节点,清空 Standby 节点的数据文件,或者使用 mv 修改目录名:
# 备份数据目录,或者可以直接清空 mv /data/pgsql12/data /data/pgsql12/data_bak # 将备份文件转移到数据目录 mv /data/pgsql12/backup /data/pgsql12/data # 修改文件属组 chown -R postgres:postgres /data/pgsql12
2.2 创建复制用户
主库创建专用于流复制的用户:
CREATE ROLE repl REPLICATION LOGIN PASSWORD 'repl123';
2.3 参数修改
PostgreSQL 使用 standby.signal
文件表示实例为 Standby 节点。在使用 pg_basebackup 备份添加 -R 参数(write configuration for replication)会在 postgresql.auto.conf
文件中写入 primary_conninfo
参数信息,这里我们需要按照实际情况调整:
primary_conninfo = 'host=172.16.104.7 port=5432 user=repl password=repl123'
2.4 启动并检查
参数配置完成后,启动 Standby 节点即可:
pg_ctl -D /data/pgsql12/data/ -l /data/pgsql12/logs/start.log start
在主节点,可通过下方 SQL 查询流复制的监控信息:
postgres=# \x Expanded display is on. postgres=# select * from pg_stat_replication; -[ RECORD 1 ]----+------------------------------ pid | 27408 usesysid | 24865 usename | repl application_name | walreceiver client_addr | 172.16.104.56 client_hostname | client_port | 40990 backend_start | 2023-09-05 14:11:56.978627+08 backend_xmin | state | streaming sent_lsn | 6/4001BB0 write_lsn | 6/4001BB0 flush_lsn | 6/4001BB0 replay_lsn | 6/4001BB0 write_lag | flush_lag | replay_lag | sync_priority | 0 sync_state | async reply_time | 2023-09-05 15:03:58.408518+08
其中 state = streaming
表示流复制状态正常,如果有异常,可以查看 error log 中的信息,或者启动的时候就 tail -f
error_log,实时关注输出的异常信息。
2.5 同步流复制
上面 2.1~2.4 是介绍如何搭建 异步
流复制。
PostgreSQL 异步流复制的缺点是当主库损坏的时候,激活备库可能会丢失一部分数据,这于 MySQL 异步复制相同,主库只管发送增量日志,挂掉后可能有部分日志从库还没有接收到,此时发生切换就会出现数据丢失,同步复制可以解决该类问题。不过需要注意的是,如果配置同步复制 Standby 节点挂掉,会导致 Priamry 节点卡住,所以一般会有多个 Standby 节点,至少保障 WAL 同步到一个 Standby 节点。
同步复制配置多加一个 synchronous_standby_names
参数,有 3 种配置方法:
synchronous_standby_names = 's1,s2,s3'
在这个例子中,如果有 s1、s2、s3 三台 Standby 节点在运行,意味着 s1 为同步节点,其他节点均为潜在同步节点,即 WAL 只需传递给 s1 节点就可以提交。
synchronous_standby_names = 'FIRST 2 (s1, s2, s3)'
在这个例子中,如果有四个后备服务器 s1、s2、s3 和 s4 在运行,两个后备服务器 s1 和 s2 将被选中为同步后备,因为它们出现在后备服务器名称列表的前部。s3 是一个潜在的同步后备,当 s1 或 s2 中的任何一个失效, 它就会取而代之。s4 则是一个异步后备因为它的名字不在列表中。
synchronous_standby_names = 'ANY 2 (s1, s2, s3)'
在这个例子中,如果有四台后备服务器 s1、s2、s3 以及 s4 正在运行,事务提交将会等待来自至少其中任意两台后备服务器的回复。s4 是一台异步后备,因为它的名字不在该列表中。
现在我们的架构是一个 Primary 节点一个 Standby 节点,现在通过修改参数调整为 同步流复制
修改主库参数:
# 其中 walreceiver 为 Standby 节点的名字,由 primary_conninfo 中的 application_name 设置 synchronous_standby_names = 'walreceiver'
修改该参数不需要重启数据库,使用 reload 重新加载配置即可:
pg_ctl reload -D /data/pgsql12/data/
在 Primary 节点查询流复制的状态信息:
postgres=# select * from pg_stat_replication; -[ RECORD 1 ]----+------------------------------ pid | 13561 usesysid | 24865 usename | repl application_name | walreceiver client_addr | 172.16.104.56 client_hostname | client_port | 42126 backend_start | 2023-09-06 17:18:48.297466+08 backend_xmin | state | streaming sent_lsn | 6/50007D0 write_lsn | 6/50007D0 flush_lsn | 6/50007D0 replay_lsn | 6/50007D0 write_lag | flush_lag | replay_lag | sync_priority | 1 sync_state | sync reply_time | 2023-09-06 17:45:00.706196+08
其中 sync_state 由 async
变为 sync
表示为同步模式。
2.6 同步复制级别
影响同步复制还需要关注一个参数 synchronous_commit
用来设置事务的同步级别:
postgres=# select * from pg_settings where name = 'synchronous_commit'; -[ RECORD 1 ]---+------------------------------------------------------ name | synchronous_commit setting | on unit | category | Write-Ahead Log / Settings short_desc | Sets the current transaction's synchronization level. extra_desc | context | user vartype | enum source | default min_val | max_val | enumvals | {local,remote_write,remote_apply,on,off} boot_val | on reset_val | on sourcefile | sourceline | pending_restart | f
- local:WAL 日志被本地持久化后(不用管远程)事务 commit 就可以返回。
- remote_write:WAL 日志被传到备库的内存中(不必等其被持久化)事务 commit 才返回。
- remote_apply:WAL 日志被传到备库并被 apply,事务 commit 才返回。
- on:WAL 日志被传到备库并被持久化(不必等其被 apply)事务 commit 才返回。
- off:不必等 WAL 日志被本地持久化,也不管是否传到远程,事务 commit 都可以立即返回。
对于同步复制,可选的值有 remote_write、remote_apply、on。
3. 流复制监控
3.1 角色判断
select pg_is_in_recovery();
判断数据库是否为主库 f
表示是主库, t
表示属于备库角色。
3.2 主库查看流复制
查看流复制信息,可以在主库查看 pg_stat_replication 视图,可以查看流复制的状态信息:
- sent_lsn:发送 WAL 的位置。
- write_lsn:备库已接收到这部分日志,但还没有刷到磁盘中。
- flush_lsn:备库已把 WAL 写入到磁盘中。
- replay_lsn:备库应用 WAL 的位置。
- sync_state:同步模式。
- state:流复制状态。
select * from pg_stat_replication;
输出结果:
postgres=# \x
Expanded display is on.postgres=# select * from pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 13561
usesysid | 24865
usename | repl
application_name | walreceiver
client_addr | 172.16.104.56
client_hostname |
client_port | 42126
backend_start | 2023-09-06 17:18:48.297466+08
backend_xmin |
state | streaming
sent_lsn | 6/50007D0
write_lsn | 6/50007D0
flush_lsn | 6/50007D0
replay_lsn | 6/50007D0
write_lag |
flush_lag |
replay_lag |
sync_priority | 1
sync_state | sync
reply_time | 2023-09-07 10:06:18.000504+08
3.3 延迟监控
使用下方 SQL 可以查看 Standby 节点落后主库多少字节 WAL 日志:
select pg_wal_lsn_diff(pg_current_wal_lsn(),replay_lsn) from pg_stat_replication;
3.4 备库查询复制信息
在备库也可以通过查询 pg_stat_wal_receiver
视图,获得流复制的监控信息:
- pid:WAL 接收进程 ID。
- status:流复制状态,只有 streaming 为正常状态。
- receive_start_lsn:WAL 接收进程启动时使用的第一个 WAL 日志的位置。
- receive_start_tli:WAL 接收进程启动时使用的第一个时间线编号。
- received_lsn:已经接收到并且已经被写入磁盘的最后一个 WAL 日志的位置。
- received_tli:已经接收到并且已经被写入磁盘的最后一个 WAL 日志的时间线编号。
- last_msg_send_time:接收到最后一条 WAL 日志消息后,向主库发回确认消息的发送时间。
- last_msg_receipt_time:备库接收到最后一条 WAL 日志消息的接收时间。
- slot_name:使用复制槽的名称。
- conninfo:连接主库的连接串,密码等安全相关的信息会被隐去。
select * from pg_stat_wal_receiver;
postgres=# \x Expanded display is on. postgres=# postgres=# select * from pg_stat_wal_receiver; -[ RECORD 1 ]---------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ pid | 113395 status | streaming receive_start_lsn | 6/5000000 receive_start_tli | 3 received_lsn | 6/50007D0 received_tli | 3 last_msg_send_time | 2023-09-07 10:20:00.207856+08 last_msg_receipt_time | 2023-09-07 10:20:00.20971+08 latest_end_lsn | 6/50007D0 latest_end_time | 2023-09-06 17:19:46.661221+08 slot_name | sender_host | 172.16.104.7 sender_port | 5432 conninfo | user=repl password=******** dbname=replication host=172.16.104.7 port=5432 fallback_application_name=walreceiver sslmode=disable sslcompression=0 gssencmode=disable krbsrvname=postgres target_session_attrs=any
到此这篇关于PostgreSQL 流复制搭建的文章就介绍到这了,更多相关PostgreSQL 流复制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!