作者:黄凯瑞 翻译:魏波
黄凯瑞
多学科的软件开发人员,专门从事C C ++软件开发,网络安全,嵌入式软件,防火墙和IT基础结构。
1
概述
PostgreSQL 12被认为是一个主要更新,包括对性能的重大改进、分区增强、索引改进、优化执行计划逻辑等。主要变化之一是删除文件recovery.conf。因此,设置流复制群集的过程已更改,在本博客中,我将演示如何在PG12中正确设置流复制。
流复制设置需要一个主群集和一个或多个从群集,这些群集将通过流传输由主生成的已归档WAL文件来复制插入到从群集数据库中。主服务器和从服务器可以驻留在通过网络连接的不同计算机上,但是在本博客中,我们将使用一个主服务器和一个从服务器设置,并且两者都将在具有不同端口号的同一台计算机上运行。
本博客中说明的过程基于Postgres版本12,该版本是从在Ubuntu 18.04上运行的源构建的。
2
主数据库群集设置
使用initdb工具创建一个主数据库集群:
$ initdb home/caryh/streaming-replication/db-master
$ cd /home/caryh/streaming-replication
/ home caryh streaming-replication是我们将在此Blog中创建的所有数据库集群的根文件夹,由于上述命令,将在此处创建db-master目录。让我们修改默认的postgreql.conf并启用以下几个重要的配置选项,以进行流复制设置。
############# db-master/postgresql.conf #############
wal_level = replica
archive_mode = on
max_wal_senders = 10
wal_keep_segments = 10
hot_standby = on
archive_command = 'test ! -f home/caryh/streaming-replication/archivedir/%f && cp %p home/caryh/streaming-replication/archivedir/%f'
port = 5432
wal_log_hints = on
上面的配置使Postgres在完成写入完整的WAL文件块时或发出pg_basebackup命令时,可以将WAL文件归档在目录/ home caryh streaming-replication archivedir /中。其中在archive_command参数中使用的%f和%p,其含义为%f将替换为目标WAL文件的文件名,而%p将替换为目标WAL文件的路径。
进行设置archive_command以确保将WAL文件归档到从属群集可以访问的位置,这一点非常重要。
请注意,wal_log_hints必须启用pg_rewind工具才能使其正常工作。我们将在下一篇博客文章中讨论有关pg_rewind的更多信息。
检查客户端身份验证文件db-master/pg_hba.conf,并确保主群集允许从从群集远程复制连接。就我而言,我的主服务器和从服务器都将在同一主机上运行,因此我将保留环回IP地址。如果您的从属群集位于另一台计算机上,请确保将正确的环回地址替换为正确的地址。
############# db-master/pg_hba.conf #############
# Allow replication connections from 127.0.0.1, by a user with the replication privilege.
# TYPE DATABASE USER ADDRESS METHOD
host replication all 127.0.0.1/32 trust
让我们继续,使用上述配置文件启动master数据库集群,创建具有复制权限的超级用户,以及一个名为clusterdb的数据库。
$ pg_ctl -D db-master start
$ createuser cary -s --replication
$ createdb clusterdb
将一些测试数据插入主群集。为简单起见,我们将向test_table插入100个整数。
$ psql -d clusterdb -U cary -c "CREATE TABLE test_table(x integer)"
CREATE TABLE
$ psql -d clusterdb -U cary -c "INSERT INTO test_table(x) SELECT y FROM generate_series(1, 100) a(y)"
INSERT 0 100
$ psql -d clusterdb -U cary -c "SELECT count(*) from test_table"
count
-------
100
(1 row)
3
从数据库集群设置
设置从属群集的目的是对当前主服务器进行备份并将其设置为备用服务器,这意味着它将从主服务器流式传输WAL文件更新并执行数据复制。
Postgres提供了几种工具和方法来执行物理数据库备份。诸如pg_start_backup('label')和pg_stop_backup()在较早的Postgres版本中很常见。在此博客中,我们将使用更新且更简单的非排他性pg_basebackup工具执行备份。两种方法都有优点和缺点,此内容不在本博客的讨论范围之内。本文在这两种方法上提供了很好的解释:
https://www.cybertec-postgresql.com/zh-CN/exclusive-backup-deprecated-what-now/
让我们使用pg_basebackup创建从集群。
$ pg_basebackup -h 127.0.0.1 -U cary -p 5432 -D db-slave -P -Xs -R
31373/31373 kB (100%), 1/1 tablespace
其中:
-h是主群集的IP
-U是允许进行复制的用户名
-p是正在运行的主群集的端口号
-D是我们要在其中设置从数据库群集的目录
-P显示进度
-Xs选择WAL流方法
-R编写一个recovery.conf文件。
此步骤与以前的PG版本有所不同。-R命令将不再在db-slave目录中输出recovery.conf文件。
$ ls db-slave
backup_label pg_dynshmem pg_multixact pg_snapshots pg_tblspc pg_xact
base pg_hba.conf pg_notify pg_stat pg_twophase postgresql.auto.conf
global pg_ident.conf pg_replslot pg_stat_tmp PG_VERSION postgresql.conf
pg_commit_ts pg_logical pg_serial pg_subtrans pg_wal standby.signal
旧的recovery.conf文件的内容将移至postgresql.conf和postgresql.auto.conf。
让我们先检查一下db-slave/postgresql.auto.conf,我们将看到pg_basebackup已经为我们创建了primary_conninfo。该行以前位于recovery.conf中,它告诉从群集应从何处
以及如何从主群集中流式传输。确保postgresql.auto.conf中存在此行。
############# db-slave/postgresql.auto.conf #############
# Do not edit this file manually!
# It will be overwritten by the ALTER SYSTEM command.
primary_conninfo = 'user=cary passfile=''/home/caryh/.pgpass'' host=127.0.0.1 port=5432 sslmode=prefer sslcompression=0 gssencmode=disable target_session_attrs=any'
让我们检查db-slave/postgresql.conf并更新一些参数。
############# db-slave/postgresql.conf #############
wal_level = replica
archive_mode = on
max_wal_senders = 10
wal_keep_segments = 10
hot_standby = on
archive_command = 'test ! -f /home/caryh/streaming-replication/archivedir/%f && cp %p /home/caryh/streaming-replication/archivedir/%f'
wal_log_hints = on
port = 5433
restore_command = 'cp /home/caryh/streaming-replication/archivedir/%f %p'
archive_cleanup_command = 'pg_archivecleanup /home/caryh/streaming-replication/archivedir %r'
由于db-slave/postgresql.conf是通过pg_basebackup从主群集直接复制的,因此我们需要将其更改为port与主端口不同的端口(在本例中为5433),因为两者都在同一台计算机上运行。我们将需要填写restore_command和archive_cleanup_command让从属群集知道如何获取已归档的WAL文件以进行流传输。这两个参数曾经在recovery.conf中定义,PG12将其移至postgresql.conf中。
请注意,在db-slave目录中,standby.signal将自动创建一个新文件,pg_basebackup指示该从集群将以standby模式运行。该文件standby.signal是PG12中的新增功能,用以替代standby_mode = 'on',以前在文件recovery.conf中定义。如果此文件不存在,请确保通过以下方式创建它:
$ touch db-slave/standby.signal
现在,让我们启动从集群:
$ pg_ctl -D db-slave start
4
验证流复制设置
一旦主集群和从集群都已设置并运行,我们应该从ps -ef命令中看到一些后端进程已启动来实现复制,即walsender和walreceiver。
$ ps -ef | grep postgres
caryh 12782 2921 0 16:12 ? 00:00:00 /usr/local/pgsql/bin/postgres -D db-master
caryh 12784 12782 0 16:12 ? 00:00:00 postgres: checkpointer
caryh 12785 12782 0 16:12 ? 00:00:00 postgres: background writer
caryh 12786 12782 0 16:12 ? 00:00:00 postgres: walwriter
caryh 12787 12782 0 16:12 ? 00:00:00 postgres: autovacuum launcher
caryh 12788 12782 0 16:12 ? 00:00:00 postgres: archiver last was 000000010000000000000002.00000028.backup
caryh 12789 12782 0 16:12 ? 00:00:00 postgres: stats collector
caryh 12790 12782 0 16:12 ? 00:00:00 postgres: logical replication launcher
caryh 15702 2921 0 17:06 ? 00:00:00 /usr/local/pgsql/bin/postgres -D db-slave
caryh 15703 15702 0 17:06 ? 00:00:00 postgres: startup recovering 000000010000000000000003
caryh 15708 15702 0 17:06 ? 00:00:00 postgres: checkpointer
caryh 15709 15702 0 17:06 ? 00:00:00 postgres: background writer
caryh 15711 15702 0 17:06 ? 00:00:00 postgres: stats collector
caryh 15713 15702 0 17:06 ? 00:00:00 postgres: walreceiver streaming 0/3000148
caryh 15714 12782 0 17:06 ? 00:00:00 postgres: walsender cary 127.0.0.1(59088) streaming 0/3000148
caryh 15728 10962 0 17:06 pts/5 00:00:00 grep --color=auto post
我们还可以通过向主集群发出查询来详细检查复制状态:
$ psql -d clusterdb -U cary -c "select * from pg_stat_replication;" -x -p 5432
-[ RECORD 1 ]----+------------------------------
pid | 15714
usesysid | 16384
usename | cary
application_name | walreceiver
client_addr | 127.0.0.1
client_hostname |
client_port | 59088
backend_start | 2019-10-29 17:06:49.072082-07
backend_xmin |
state | streaming
sent_lsn | 0/3000148
write_lsn | 0/3000148
flush_lsn | 0/3000148
replay_lsn | 0/3000148
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
reply_time | 2019-10-29 17:10:09.515563-07
最后,我们可以将其他数据插入主群集,并验证从属群集是否也更新了数据。
# Query slave cluster
$ psql -d clusterdb -U cary -c "SELECT count(*) from test_table" -p 5433
count
-------
100
(1 row)
# Query master cluster
$ psql -d clusterdb -U cary -c "SELECT count(*) from test_table" -p 5432
count
-------
100
(1 row)
# Insert more data to master cluster
$ psql -d clusterdb -U cary -c "INSERT INTO test_table(x) SELECT y FROM generate_series(1, 100) a(y)" -p 5432
INSERT 0 100
# Query slave cluster again
psql -d clusterdb -U cary -c "SELECT count(*) from test_table" -p 5433
count
-------
200
(1 row)
现在,主群集和从群集都已同步。
5
设置复制槽
前面的步骤说明了如何正确设置主群集和从群集之间的流复制。但是,在某些情况下,由于某些原因,从属服务器可能会断开连接,从而导致时间延长,并且当某些未复制的WAL文件被回收或从wal_keep_segments参数控制的主群集中删除时,可能无法与主服务器进行复制。
复制槽确保主服务器可以为所有从服务器保留足够的WAL段,防止主服务器删除可能导致从服务器上发生恢复冲突的行。
让我们在主集群上创建一个复制槽slave:
$ psql -d clusterdb -U cary -c "select * from pg_create_physical_replication_slot('slave')" -p 5432
slot_name | lsn
-----------+-----
slave |
(1 row)
$ psql -d clusterdb -U cary -c "select * from pg_replication_slots" -x -p 5432
-[ RECORD 1 ]-------+---------
slot_name | slave
plugin |
slot_type | physical
datoid |
database |
temporary | f
active | f
active_pid |
xmin |
catalog_xmin |
restart_lsn |
confirmed_flush_lsn |
我们刚刚在master上创建了复制槽slave,该复制槽当前未处于活动状态(active = f)。
让我们修改从属服务器postgresql.conf并使其连接到主服务器的复制槽
############# db-slave/postgresql.conf #############
primary_slot_name = 'slave'
请注意,这个参数primary_slot_name我们也曾经定义在recovery.conf中,PG12移至postgresql.conf中。更改后,我们需要重新启动从节点。
$ pg_ctl -D db-slave stop
$ pg_ctl -D db-slave start
如果一切正常,则检查主服务器上的复制槽的插槽状态应为活动状态。
$ psql -d clusterdb -U cary -c "select * from pg_replication_slots" -x -p 5432
-[ RECORD 1 ]-------+----------
slot_name | slave
plugin |
slot_type | physical
datoid |
database |
temporary | f
active | t
active_pid | 16652
xmin |
catalog_xmin |
restart_lsn | 0/3003B98
confirmed_flush_lsn |
6
总结
在此博客中,我们讨论了如何在PG12中设置流复制群集,其中从旧版本更改了几个步骤,尤其是删除了recovery.conf。
这是与复制设置相关更改的简短列表,这些更改已从 recovery.conf
· restore_command =>移至 postgresql.conf
· recovery_target_timeline =>已移至 postgresql.conf
· Standby_mode =>替换为 standby.signal
· primary_conninfo =>移至postgresql.conf或postgresql.auto.conf
· archive_cleanup_command =>移至 postgresql.conf
· primary_slot_name =>移至 postgresql.conf