一、规划
master 192.168.84.9
slave 192.168.84.10
需求:master和slave作为主从流复制,当master宕机后,slave切换为新主继续服务;然而当master恢复故障后,作为从重新加入主从流复制。
二、部署
2.1克隆虚拟机 略
2.2创建用户
postgres=# create user rep replication password 'rep';
CREATE ROLE
复制
2.3 修改主库配置文件
postgresql.conf listen_address = '*' wal_level = replica archive_mode = on archive_command = 'cp %p /usr/local/pgsql/pgarch/%f' max_wal_senders= 10 wal_keep_segments=1024 hot_standby = on
复制
参数简要说明:
listen_address: 按需设置,本次测试配置为所有主机均可以访问,生产环境可以按需配置网段或IP等
wal_level: 设置流复制模式至少设置为replica
archive_mode: 本次启用归档
archive_command:WAL日志归档命令,生产环境可以将归档拷贝到对应目录或其他机器上,本次测试配置为归档到本机的另一个目录下
max_wal_senders: 最大WAL发送进程数,此数量需大于等于从库个数且比max_connections小。
wal_keep_segments: pg_wal目录下保留WAL日志的个数,每个WAL文件默认16M,为保障从库能在应用归档落后时依旧能追上主库,此值建议设置较大一点。
hot_standby: 此参数控制在恢复归档期间是否支持只读操作,设置为ON后从库为只读模式。
注意: 上述参数中有涉及归档日志的路径,需手动创建
mkdir -p /usr/local/pgsql/pgarch/
2.4 修改配置文件pg_hba.conf
添加复制账号的权限,因可能会主从切换,因此 主从机器的IP均添加。也可以设置网段,以便于后期添加从库。
# replication privilege.
local replication all trust
host replication all 127.0.0.1/32 trust
host replication all ::1/128 trust
host replication all 192.168.84.9/24 md5
host replication all 192.168.84.10/24 md5
复制
5、备份数据
从机上在线备份主库数据,并将数据放在指定路径,此路径建议与主库路径一致。可以使用pg_basebackup命令在线热备份,具体命令如下:
[postgres@pgstandby pgdata]$ pg_basebackup -h 192.168.84.9 -U rep -p 5432 -F p -X s -v -P -R -D /usr/local/pgsql/pgdata -l rep_backup
复制
口令: pg_basebackup: 开始基础备份,等待检查点完成 pg_basebackup: 已完成检查点 pg_basebackup: 预写日志起始于时间点: 0/1F000028, 基于时间轴1 pg_basebackup: 启动后台 WAL 接收进程 pg_basebackup: 已创建临时复制槽"pg_basebackup_1752" 33675/33675 kB (100%), 1/1 表空间 pg_basebackup: 预写日志结束点: 0/1F000100 pg_basebackup: 等待后台进程结束流操作... pg_basebackup: 同步数据到磁盘... pg_basebackup: 基础备份已完成pg_basebackup命令中的参数说明: -h 指定连接的数据库的主机名或IP地址,这里就是主库的ip -U 指定连接的用户名,此处是我们刚才创建的专门负责流复制的repl用户 -F 指定生成备份的数据格式,支持p(plain原样输出)或者t(tar格式输出) -X 表示备份开始后,启动另一个流复制连接从主库接收WAL日志,有 f(fetch)和s (stream)两种方式,建议使用s方式 -P 表示显示数据文件、表空间传输的近似百分比 允许在备份过程中实时的打印备份的进度 -v 表示启用verbose模式,命令执行过程中会打印各阶段日志,建议启用 -R 表示会在备份结束后自动生成recovery.conf文件,这样也就避免了手动创建 -D 指定把备份写到哪个目录,这里尤其要注意一点就是做基础备份之前从库的数据目录(/data/postgresql/data)目录需要手动清空 -l 表示指定个备份的标识,运行命令后可以看到进度提示
复制
从以上日志信息看出pg_basebackup命令首先对数据库做一次checkpoint,之后基于时间点做一个全库基准备份,全备过程中会拷贝$PGDATA数据文件和表空间文件到备库节点对应目录。
2.5 修改standby.signal
以上备份命令中生成了standby.singnal文件,因此简单修改即可。 [postgres@pgstandby pgdata]$ cat standby.signal standby_mode = ‘on’
复制
2.6 修改postgres.conf
primary_conninfo = ‘host=192.168.84.9 port=5432 user=rep password=rep’ recovery_target_timeline = ‘latest’ hot_standby = on max_standby_streaming_delay = 30s wal_receiver_status_interval = 10s hot_standby_feedback = on
复制
参数说明:
standby_mode: 设置是否启用数据库为备库,如果设置成on,备库会不停地从主库上获取WAL日志流,直到获取主库上最新的WAL日志流
primary_conninfo:设置主库的连接信息,这里设置了主库IP、端口、用户名信息等,此处是明文密码,生产环境建议配置非明文密码,而是将密码配置在另一个隐藏文件中
covery_target_timeline: 设置恢复的时间线(timeline),默认情况下是恢复到基准备份生成时的时间线,设置成latest表示从备份中恢复到最近的时间线,通常流复制环境设置此参数为latest,复杂的恢复场景可将此参数设置成其他值.
recovery_target_timeline ( ``string): 指定恢复到特定时间轴。默认设置是沿着执行基本备份时的当前时间线恢复。将此设置为 latest 将恢复到存档中找到的最新时间轴,这在备用服务器中很有用。
hot_standby” 为“on”,说明备库是“Hot Standby”,即可以只读的,如果配置“hot_standby” 为“off”,说明备库是“Warm Standby”,psql是无法连接这个备库的
max_standby_streaming_delay: 适用于WAL数据从流复制接收到。 默认值是30秒。如果不指定,则单位是毫秒。 值为-1允许待机永远等待完成查询冲突。 这个参数只能在postgresql.conf文件或服务器命令行上设置。
wal_receiver_status_interval: 备机向主机发送相关复制信息的最小频率,小于等于零说明不需要发送
hot_standby_feedback: 配置该参数之后备库会定期向主库通知最小活跃事务id(xmin)值,这样使得主库vacuum进程不会清理大于xmin值的事务。
2.7 启动从库
直接使用pg_ctl或配置服务启动从库即可。
[postgres@pgstandby pgdata]$ pg_ctl -D $PGDATA -l /tmp/logfile start
等待服务器进程启动 … 完成
服务器进程已经启动
复制
[postgres@pgstandby pgdata]$ ps -ef|grep postgres root 2419 1339 0 23:34 pts/0 00:00:00 su - postgres postgres 2421 2419 0 23:34 pts/0 00:00:00 -bash postgres 3004 1 0 23:45 ? 00:00:00 /usr/local/pgsql/bin/postgres -D /usr/local/pgsql/pgdata postgres 3005 3004 0 23:45 ? 00:00:00 postgres: logger postgres 3006 3004 0 23:45 ? 00:00:00 postgres: startup recovering 000000010000000000000020 postgres 3007 3004 0 23:45 ? 00:00:00 postgres: checkpointer postgres 3008 3004 0 23:45 ? 00:00:00 postgres: background writer postgres 3009 3004 0 23:45 ? 00:00:00 postgres: stats collector postgres 3010 3004 0 23:45 ? 00:00:00 postgres: walreceiver postgres 3046 2421 0 23:46 pts/0 00:00:00 ps -ef postgres 3047 2421 0 23:46 pts/0 00:00:00 grep --color=auto postgres
复制
三、检查
3.1 主库
postgres=# select * from pg_stat_replication;
pid | usesysid | usename | application_name | client_addr | client_hostname | client_port | backend_
start | backend_xmin | state | sent_lsn | write_lsn | flush_lsn | replay_lsn | write_lag | flush
_lag | replay_lag | sync_priority | sync_state | reply_time
------+----------+---------+------------------+---------------+-----------------+-------------+-----------------
--------------+--------------+-----------+------------+------------+------------+------------+-----------+------
-----+------------+---------------+------------+-------------------------------
1830 | 16479 | rep | walreceiver | 192.168.84.10 | | 57638 | 2022-11-16 23:45
:42.303126+08 | 575 | streaming | 0/20000148 | 0/20000148 | 0/20000148 | 0/20000148 | |
| | 0 | async | 2022-11-16 23:47:33.247604+08
(1 行记录)
复制
select pid,usesysid,usename,client_addr,state,sync_state from pg_stat_replication;
复制
3.2 从库
从库检查进程:
ps -ef |grep postgres |grep -v grep |grep receiver
复制
字段state显示的同步状态有:startup(连接中)、catchup(同步中)、streaming(同步); 字段sync_state显示的模式有:async(异步)、sync(同步)、potential(虽然现在是异步模式,但是有可能升级到同步模式)
复制
从库检查日志接受状态:
postgres=# select * from pg_stat_wal_receiver;
pid | status | receive_start_lsn | receive_start_tli | received_lsn | received_tli | last_msg_send_time | last_
msg_receipt_time | latest_end_lsn | latest_end_time | slot_name | sender_host | sender_port | conninfo
-----+--------+-------------------+-------------------+--------------+--------------+--------------------+------
-----------------+----------------+-----------------+-----------+-------------+-------------+----------
(0 行记录)
复制
四、测试
4.1 测试主从同步
在主库创建表并新增数据
[root@pgclass ~]# psql -h 192.168.84.9 -p 5432 -U postgres
用户 postgres 的口令:
psql (11.5, 服务器 12.12)
警告:psql 主版本11,服务器主版本为12.
一些psql功能可能无法正常使用.
输入 "help" 来获取帮助信息.
postgres=# \c woo
psql (11.5, 服务器 12.12)
警告:psql 主版本11,服务器主版本为12.
一些psql功能可能无法正常使用.
您现在已经连接到数据库 "woo",用户 "postgres".
woo=# \l
数据库列表
名称 | 拥有者 | 字元编码 | 校对规则 | Ctype | 存取权限
-----------+----------+----------+-------------+-------------+-----------------------
postgres | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
template0 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
template1 | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 | =c/postgres +
| | | | | postgres=CTc/postgres
woo | postgres | UTF8 | en_US.UTF-8 | en_US.UTF-8 |
(4 行记录)
woo=# create table rep (id int primary key, name varchar(20));
CREATE TABLE
woo=# insert into rep values(1,'aaa'),(2,'abc');
INSERT 0 2
woo=#
复制
在从库查看
[postgres@PG33 data]$ psql
psql (11.4)
Type "help" for help.
woo=# select * from rep;
id | name
----+------
1 | aaa
2 | abc
(2 行记录)数据已正常同步
复制
4.2 查看复制状态
通过pg_stat_replication视图可以查看复制状态
woo=# select pid ,usesysid,usename,client_addr,state,sync_state from pg_stat_replication;
pid | usesysid | usename | client_addr | state | sync_state
------+----------+---------+---------------+-----------+------------
1830 | 16479 | rep | 192.168.84.10 | streaming | async
(1 行记录)
复制
以上查询结果sync_state字段值为async,表示主备数据复制使用异步方式;state值为streaming,表示流复制方式。
4.3 调整为同步复制
前面的步骤部署的为异步复制,如想配置为同步复制,则调整recovery.conf配置文件里的 synchronous_commit及synchronous_standby_names 后重启或reload即可。
synchronous_commit = remote_write synchronous_standby_names = '*'
复制
之后再查看结果如下:
postgres=# select pid ,usesysid,usename,client_addr,state,sync_state from pg_stat_replication;
pid | usesysid | usename | client_addr | state | sync_state
-------+----------+---------+----------------+-----------+------------
1830 | 16497 | repl | 192.168.84.10 | streaming | sync
(1 row)
复制
此时状态已变为同步复制了。
注: synchronous_commit 有多种方式,在流复制模式下,主要设置情况如下:
remote_write: 当流复制主库提交事务时,需等待备库接收主库发送的WAL日志流并写入备节点操作系统缓存中,之后向客户端返回成功,这种情况下备库实例出现异常关闭时不会有已传送的WAL日志丢失风险,但备库操作系统异常宕机就有已传送的WAL丢失风险了,此时WAL可能还没完全写入备节点WAL文件中,简单地说remote_write表示本地WAL已落盘,备库的WAL还在备库操作系统缓存中,也就是说只有一份持久化的WAL,这个选项带来的事务响应时间较低
on: 设置成on表示流复制主库提交事务时,需等待备库接收主库发送的WAL日志流并写入WAL文件,之后才向客户端返回成功,简单地说on表示本地WAL已落盘,备库的WAL也已落盘,也就是说有两份持久化的WAL,但备库此时还没有完成重做,这个选项带来的事务响应时间较高。
remote_apply: 表示表示流复制主库提交事务时,需等待备库接收主库发送的WAL并写入WAL文件,同时备库已经完成重做,之后才向客户端返回成功,简单地说remote_apply表示本地WAL已落盘,备库WAL已落盘并且已完成重做,这个设置保证了拥有两份持久化的WAL,同时备库也完成了重做,这个选项带来的事务响应时间最高,即性能最差。