postgresql warm standby

异步流复制

要求

这里使用一个mater (192.168.1.1) 和一个 maid (192.168.1.2) 来举例

master 设置

第一步

初始化 PGDATA

$ ls
master/
$ pg_ctl -D master initdb

第二步

修改postgresql.conf

第三步

启动数据库

$ ls
master/
$ pg_ctl -D master start

登录数据库创建复制用的用户

$ psql
postgres# CREATE ROLE maid REPLICATION LOGIN ENCRYPTED PASSWORD 'maid';

maid用户创建复制slot

postgres# SELECT * FROM pg_create_physical_replication_slot('maid_slot');

创建复制slot的原因是因为master会回收WAL(write ahead log)分段,但这时maid可能还没有接收到这个数据。
其实解决这个问题有两个方法: - 一种是把wal_keep_segments设置得足够大,这样可以保证分段不会太早被回收
- 另一种是设置replication slot,这种方式数据库会自动的发现WAL是否应该被回收,(我们这里用这种)

第四步

修改 pg_hba.conf 追加如下行,让maid可以通过刚创建的maid用户连接到master

host    replication     maid             192.168.1.2/32           md5

其中maid 为 master 中创建的用户,192.168.1.2 为maid机器的ip,md5是验证方式

第五步

重启master

$ ls
master/
$ pg_ctl -D master restart

maid 设置

第一步

复制master的 PGDATA 目录到本机,如果有postmaster.pid,那么删掉它。 如:

# master (192.168.1.1)
$ tar cfJ master.txz master
$ scp master.txz root@192.168.1.2/srv

# maid (192.168.1.2)
$ cd /srv
$ tar xf master.txz
$ mv master maid
$ cd maid
$ rm -f postmaster.pid

第二步

创建 maid/recovery.conf 填充以下类容

standby_mode = 'on'

# master中的maid用户
primary_conninfo = 'host=192.168.1.1 user=maid password=maid port=5432'

# 在master数据库中创建的 replication slot
primary_slot_name = 'maid_slot'

# 设置为 latest 将恢复到备份中找到的最新时间轴
recovery_target_timeline = 'latest'

# 如果master挂了,需要切换maid到master 创建这文件即可自动切换
trigger_file = '/tmp/pg_trigger'

第三步

启动maid

$ pg_ctl -D maid start

同步流复制

同样要求master和maid的PGDATA一致,这里以同一台机器为例。 master 监听 5432 端口, maid 监听 5433 端口

master

配置与异步流复制相同,另外需要设置 synchronous_standby_names = '*' 以及 synchronous_commit = on

maid

由于在同一台机器上,所以需要修改监听端口,这里改为 5433,其余配置和异步流复制完全一致。

如果多个有maid备份且synchronous_standby_names有优先级考虑的话,可以在recovery.conf中给每个maid指定一个应用名,如:

 primary_conninfo = 'application_name=maid_1 host=192.168.1.1 user=maid password=maid port=5432'

这时 synchronous_standby_name 可以指定规则,详见这里

结果举例:

同步:

postgres=# select * from pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid              | 11552
usesysid         | 16384
usename          | maid
application_name | maid_1
client_addr      | 127.0.0.1
client_hostname  |
client_port      | 40082
backend_start    | 2020-03-06 13:27:59.558948+08
backend_xmin     |
state            | streaming
sent_lsn         | 0/16CE440
write_lsn        | 0/16CE440
flush_lsn        | 0/16CE440
replay_lsn       | 0/16CE440
write_lag        |
flush_lag        |
replay_lag       |
sync_priority    | 1
sync_state       | sync

postgres=#

异步(注释掉以上master中的更改):

postgres=# select * from pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid              | 7271
usesysid         | 16384
usename          | maid
application_name | maid_1
client_addr      | 127.0.0.1
client_hostname  |
client_port      | 47306
backend_start    | 2020-03-06 16:55:07.339901+08
backend_xmin     |
state            | streaming
sent_lsn         | 0/16CD4F0
write_lsn        | 0/16CD4F0
flush_lsn        | 0/16CD4F0
replay_lsn       | 0/16CD4F0
write_lag        |
flush_lag        |
replay_lag       |
sync_priority    | 0
sync_state       | async

异步和同步的区别

同步需要在master配置中开启synchronous_commit 及设置 synchronous_standby_names。 流复制默认是异步的,好处是可用性高,坏处是容易丢失更多数据。 同步的好处是master会确认一个事务是否已经同步到了一个或多个standby(由 synchronous_standby_names 配置),坏处是可用性低。

参考

https://www.postgresql.org/docs/10/warm-standby.html

注意

Windows 不支持 tcp_keepalives_count 选项