一 主备机器规划主机名
主:192.168.2.103 db1
备:192.168.2.104 db2
二 创建流复制
2.1 修改主机配置(两台主机都修改)
$ cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.2.103 db1
192.168.2.104 db2
2.2 在主库设置
1) 初始化新数据库
pg_ctl init -D /pgdata/data
2) 启动数据库
pg_ctl -D /pgdata/data start
3)建立同步用户
postgres=# create role repl login replication encrypted password 'repl';
CREATE ROLE
4)配置$PGDATA/data/pg_hba.conf
host replication repl db2 trust
host replication repl 192.168.2.0/24 trust
host all all 192.168.2.0/24 trust
注意:备库也做同样的配置(注意修改主机名),为了后面的主备切换
5)配置$PGDATA/data/postgres.conf
listen_addresses = '*'
wal_level = replica
max_wal_senders=10
archive_mode = on
archive_command = 'cp %p /home/postgres/arch/%f'
restore_command = 'cp /home/postgres/arch/%f %p'
recovery_target_timeline = 'latest'
full_page_writes = on
wal_log_hints = on logging_collector = on
log_directory = 'pg_log'13 log_filename = 'postgresql-%Y-%m-%d.log'
6)重启让配置生效
pg_ctl -D /pgdata/data restart
2.3 在备库设置
1)不需要初始化,直接从主库备份就行
pg_basebackup -h db1 -p 5432 -U repl -R -F p -P -D /pgdata/data
2)备库修改配置文件
listen_addresses = '*'
wal_level = replica
max_wal_senders=10
archive_mode = on
archive_command = 'cp %p /home/postgres/arch1/%f' --设置归档 cp 命令
restore_command = 'cp /home/postgres/arch1/%f %p'
recovery_target_timeline = 'latest'
full_page_writes = on
wal_log_hints = on logging_collector = on
log_directory = 'pg_log'
log_filename = 'postgresql-%Y-%m-%d.log'
--以下参数因为使用pg_basebackup不需要重复设置 hot_standby = on #在备份的同时允许查询,默认值
max_standby_streaming_delay = 30s #可选,流复制最大延迟
wal_receiver_status_interval = 10s #可选,从向主报告状态的最大间隔时间
hot_standby_feedback = on #可选,查询冲突时向主反馈
3)配置$PGDATA/data/pg_hba.conf
host replication repl db1 trust #这里修改主机名为主机的
host replication repl 192.168.2.0/24 trust
host all all 192.168.2.0/24 trust
4)创建备库文件 standby.signal
touch standby.signal
#连接到主库信息
primary_conninfo = 'host=db1 port=5433 user=repl password=repl options=''-c wal_sender_timeout=5000'''
#将来变成主库时需要用到的参数。
restore_command = 'cp /home/postgres/arch1/%f %p'
#变成主库后需要清空的归档日志
archive_cleanup_command = 'pg_archivecleanup /home/postgres/arch1 %r'
#把备库变成 read-only transaction 模式
standby_mode = on
5)重启让配置生效
pg_ctl -D /pgdata/data restart
三、验证
3.1 查看主备进程
主
[postgres@db1 pg_wal]$ ps -ef|grep wal
postgres 58923 58918 0 02:46 ? 00:00:00 postgres: walwriter
postgres 59341 58918 0 02:52 ? 00:00:00 postgres: walsender repl 192.168.2.104(60618) streaming 0/5000060
备
[postgres@db2 pg_wal]$ ps -ef|grep wal
postgres 69657 69648 0 02:52 ? 00:00:00 postgres: walreceiver streaming 0/5000060
3.2 主库切换日志
postgres=# select pg_switch_wal();
pg_switch_wal
---------------
0/4000160
(1 row)
查看备库WAL日志同步情况
3.3 查看当前备库状态:
select pg_is_in_recovery();
t :true,意味着处于 recovery 状态
f :false,意味着处于正常服务状态
3.4 主库查询
postgres=# \x
Expanded display is on.
postgres=# select * from pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 59341
usesysid | 16388
usename | repl
application_name | walreceiver
client_addr | 192.168.2.104
client_hostname | db2
client_port | 60618
backend_start | 2023-12-10 02:52:19.435147+08
backend_xmin |
state | streaming
sent_lsn | 0/7000148
write_lsn | 0/7000148
flush_lsn | 0/7000148
replay_lsn | 0/7000148
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
reply_time | 2023-12-10 02:59:39.394891+08
sync_state表示同步模式
sent_lsn表示发送日志的起点
reply_time表示应用日志的起点
3.5 备库数据库日志内容
2023-12-10 02:52:19.437 CST [69657] LOG: started streaming WAL from primary at 0/4000000 on timeline 1
2023-12-10 02:57:19.469 CST [69650] LOG: restartpoint starting: time
2023-12-10 02:57:19.476 CST [69650] LOG: restartpoint complete: wrote 1 buffer s (0.0%); 0 WAL file(s) added, 0 removed, 4 recycled; write=0.001 s, sync=0.001 s, total=0.007 s; sync files=0, longest=0.000 s, average=0.000 s; distance=6553 6 kB, estimate=65536 kB
2023-12-10 02:57:19.476 CST [69650] LOG: recovery restart point at 0/7000060
四、主从切换
这里建议把wal保留参数调大,保证切换过程中,原备库的日志和原主库的日志LSN同步
▪ min_wal_size
▪ wal_keep_size
4.1 停止主库
pg_ctl -D /pgdata/data stop
4.2 备库上执行命令,提升为主备
执行以下命令进行主从切换,把备库改成主库,执行之后发现 standby.signal 被删除了
pg_ctl promote 查看最新状态:
pg_controldata | grep cluster
Database cluster state: in production
4.3 修改postgresql.auto.conf
primary_conninfo = 'user=repl passfile=''/home/postgres/.pgpass'' host=pg1 port=1922 sslmode=disable
sslcompression=0 gssencmode=disable krbsrvname=postgres target_session_attrs=any'
重启数据库,查看后台进程,此时未发现walsender进程
ps -ef|grep postgres
4.4 在新备库上(原主库)创建一个 standby.signal文件,添加如下内容:
primary_conninfo = 'host=db2 port=5433 user=repl password=repl options=''-c wal _sender_timeout=5000'''
restore_command = 'cp /home/postgres/arch1/%f %p'
archive_cleanup_command = 'pg_archivecleanup /home/postgres/arch1 %r'
standby_mode = on
4.5 在新备库的 postgresql.auto.conf 文件中添加
如下内容:
primary_conninfo = 'user=repl passfile=''/home/postgres/.pgpass'' channel_bindi ng=prefer host=db2 port=5433 sslmode=prefer sslcompression=0 sslsni=1 ssl_min_p rotocol_version=TLSv1.2 gssencmode=prefer krbsrvname=postgres target_session_attrs=any'
注意/home/postgres/.pgpass 其实没有没有这个文件,不需要创建。
4.6 启动新备库:
pg_ctl start
4.7 验证主备库是否能够同步
在主库进行 dml 操作,发现备库能够正常同步,切换成功。
五、实时同步
上面的配置是异步同步,对于主库的性能影响是最小的,但是会丢数据,我们可以把复制配置成
实时同步。
当设置同步复制时:
• 最小化延迟
• 确保您有冗余延迟
• 同步复制比异步复制代价更高同步时是通过一个关键的参数 application_name 来实现的。
5.1 配置主库 postgres.conf,添加如下内容:
synchronous_standby_names = 'standby_pg2'
synchronous_commit = on
5.2 重启主库
pg_ctl restart
5.3 修改备库 standby.signal 配置文件
在原来的内容中添加 application_name 内容
primary_conninfo = 'host=pg1 application_name=standby_pg2 port=1922 user=repl password=oracle options=''-c wal_sender_timeout=5000'''
restore_command = 'cp /home/postgres/arch/%f %p'
archive_cleanup_command = 'pg_archivecleanup /home/postgres/arch %r'
standby_mode = on
5.4 修改备库 postgresql.auto.conf
添加 application_name 内容,实际上备库是以这个文件为主,上面修改的 standby.signal 并不生效:
primary_conninfo = 'user=repl passfile=''/home/postgres/.pgpass'' channel_binding=prefer host=db2 application_name=standby_pg2 port=5433 sslmode=prefer sslcom pression=0 sslsni=1 ssl_min_protocol_version=TLSv1.2 gssencmode=prefer krbsrvna me=postgres target_session_attrs=any'
5.5 重启备库,查看后台日志信息:
consistent recovery state reached at 0/21000188
5.6、在主库查看同步状态:
postgres=# \x
Expanded display is on.
postgres=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 75433
usesysid | 16388
usename | repl
application_name | standby_pg2
client_addr | 192.168.2.103
client_hostname | db1
client_port | 57420
backend_start | 2023-12-10 04:17:12.048633+08
backend_xmin |
state | streaming
sent_lsn | 0/110000D8
write_lsn | 0/110000D8
flush_lsn | 0/110000D8
replay_lsn | 0/110000D8
write_lag |
flush_lag |
replay_lag |22 sync_priority | 1
sync_state | sync
reply_time | 2023-12-10 04:17:22.111778+08
状态显示为实时同步。
5.7 验证备库关闭
#备库
[postgres@db1 data]$ pg_ctl -D /pgdata/data/ stop
waiting for server to shut down.... done
server stopped #主备
postgres=# create table t1 as select * from pg_class;
。。。。。等待中
备库关闭之后,主库执行DML操作HANG住。
5.8 多个从库的配置
如果我们配置了多个备库,而且进行实时同步,假如只要保证前面的备库能够实时就可以,那么
可以进行如下设置:
synchronous_standby_names = 'FIRST 2 (s1, s2, s3)'
如果只要保证其中任何的备库同步成功,可以进行如下设置:
synchronous_standby_names = 'ANY 2 (s1, s2, s3)'
六、添加节点
6.1 修改 standby.signal 和postgres.auto.conf 文 件
1)三节点还原主备
pg_basebackup -h db2 -p 5433 -U repl -R -F p -P -D /pgdata/data2 2)修改三节点端口号
port=5433 3)修改三节点postgres.auto.conf
primary_conninfo = 'user=repl passfile=''/home/postgres/.pgpass'' channel_bindi ng=prefer host=db2 application_name=standby_pg2 port=5433 sslmode=prefer sslcom pression=0 sslsni=1 ssl_min_protocol_version=TLSv1.2 gssencmode=prefer krbsrvna me=postgres target_session_attrs=any'
6.2 修改主库的 postgres.conf,添加如下一行:
synchronous_standby_names = 'standby_pg3'
synchronous_commit = on synchronous_standby_names = 'FIRST 2 (standby_pg2,standby_pg3)'
6.3 重启主库,查看复制状态:
pg_ctl restart testdb=# \x
Expanded display is on.
testdb=# select * from pg_stat_replication
6.4 验证同步
主要备库的任何一个节点无法同步,都会影响主库的事务操作。但是发现正常的一个备库节点能够同步,即使主库处于停留状态,由此证明主库已经把事务传递到备库了,只是有备库没有同步,所以处于等待状态。
6.5 如果把主库的参数修改如下:
synchronous_standby_names = 'FIRST 1 (standby_pg2,standby_pg3)'
实验证明,如果第二个备库节点发生故障无法同步,不会影响主库事务操作。