[翻译]手把手教你配置流复制

原文

尽管许多人知道流复制,这篇博客是为初学者准备的,我将从必要条件和一些关于流复制的介绍开始。:-)

必要条件:

  1. 在各自的服务器上安装相同版本的PostgreSQL数据库。

  2. 配置”postgres”用户的无密码ssh认证(译注:如使用ssh的公私密匙)

  3. 生产环境的服务器必须在postgresql.conf文件配置通过设置archive_modearchive_command参数来开启WAL归档模式

  4. 生产环境的服务器和备份服务器之间应该一直拥有连接以让归档的WAL文件从生产环境的服务器传输到备份服务器.

  5. 明确地配置好你的备份机的环境和目录结构要与生产服务器的一样。

介绍

它是一个异步机制;所以备机是延迟于主服务器。但不同于其他复制方法,这个延迟是非常短的,可能是一个单事务的延迟,这取决于网速,数据库负载以及流复制配置。此外,在主机上对每个备机的负载是最小的,允许一个主服务器支持多个备机。

这个特性包含在PostgreSQL 9.0中,伴随的第二个数据库实例(译注:指stand-by是依赖于主服务器的二进制日志,在这期间会标记备机服务器只能接受只读请求)

这是实践步骤所需命令:

1.到主服务器,然后创建一个带有复制权限的replication用户。例如:

1
2
3
4
5
6
7
$ psql
Password for user postgres:
psql.bin (9.2.1) Type "help" for help.
postgres=# create user replication with replication password '<password>';

2.我们需要在主服务器的/opt/PostgreSQL92/data/(译注:就是postgresql的数据目录)目录修改postgresql.conf参数以及pg_hba.conf的验证参数。设置好连接及验证,以让备机服务器可以成功地连接到主服务器的replication这个假的数据库。

1
2
3
4
5
6
7
8
$ $EDITOR postgresql.conf
listen_addresses = '*'
$ $EDITOR pg_hba.conf
#备机服务器必须有超级用户身份的访问权限
host replication replication 10.176.0.0/16 md5

3.在主服务器上设置流复制相关的参数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$EDITOR postgresql.conf
#为了在备机服务器上开始“只读”查询,wal_level必须设置成“hot_standby”. 但是,如果你一直不会在stand-by模式下连接到备机,你可以选择“archive”
wal_level = hot_standby
#设置允许备机的最大并发连接数
max_wal_senders = 5
#为了防止主服务器在循环利用WAL段文件前移动备机服务器所要求的WAL段文件,设置保留在 pg_xlog 目录里最小的段文件数。
wal_keep_segments = 32
#在主服务器上开启WAL归档到一个归档目录以让备服务器获取。如果"wal_keep_segments"值足够大以保留备机所要求的WAL段文件数,这可能就不必要开启。
archive_mode = on
archive_command = 'cp %p <archive location>%f && scp %p postgres@10.176.112.189:<archive location>/%f'

注意:在 postgresql文件里修改以上参数时,要重启服务器。

4.在主服务器上重启postgres并检查参数是否生效。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
postgres=# show archive_command ;
archive_command
-----------------
cp %p /var/PG92_Archives/%f
(1 row)
postgres=# show archive_mode ;
archive_mode
-------------
on
(1 row)
postgres=# show wal_level ;
wal_level
------------
hot_standby
(1 row)
postgres=# show max_wal_senders ;
max_wal_senders
----------------
5
(1 row)
postgres=# show wal_keep_segments ;
wal_keep_segments
------------------
32

5.对主服务器的数据目录做一个基础备份。

1
2
3
4
5
6
7
8
9
10
11
$ psql ­c "SELECT pg_start_backup('label', true)"
$ cp /opt/PostgreSQL92/data/* backup/
$psql ­c "SELECT pg_stop_backup()"
-- 打包备份目录并传输到备机的数据目录下
$tar ­cvzf backup.tar backup/
$scp backup.tar postgres@10.176.112.189:/opt/PostgreSQL92/

6.移动备机的数据内容到其他的位置,解压备份的文件并复制解压后的数据到备机的数据目录。

7.在备服务器上像主服务器那样设置复制相关的参数,连接以及验证,以便让备服务器在主服务器宕机之后可以切换成主服务器。

8.在备服务器上开启只读查询。但如果在主服务器上的wal_level参数值是archive,那hot_standby就不需要更改(即是:off)

1
2
$ $EDITOR postgresql.conf
hot_standby = on

9.在备机服务器上创建一个恢复命令文件,以下参数对于流复制是必需的。、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
$ $EDITOR recovery.conf
# 指明是否开启服务器作为一个备机。在流复制里,这个参数必须要开启。
standby_mode = 'on'
# 指明用于备服务器连接到主服务器的连接字符串。
primary_conninfo = 'host=10.176.112.188 port=5432 user=replication
password=<password> application=<app_name>'
# 指定一个触发文件让备服务器感觉到它的时候就会停止流复制(即:故障转移)
trigger_file = '<any path="">' ===> 不要创建这个文件。当你想主从切换的时候才需要创建它。
# 指定一个命令从WAL归档中加载归档段文件。如果“wal_keep_segments”是一个足够大的数值以保留WAL段文件满足备机的要求,这可能不是必要的。但一个高负载情况下可能会导致段文件在备服务器完全同步之前就已经循环利用的,这时就要求你重新开始一个新的基础备份。
restore_command = 'cp <archive_location>%f "%p"'
</archive_location></any>

10.在备服务器上启动postgres。它就会开始流复制并且你会看到像以下的信息:

1
2
3
4
LOG: entering standby mode
LOG: consistent recovery state reached at 0/1D000078
LOG: record with zero length at 0/1D000078
LOG: streaming replication successfully connected to primary

11.你可以通过比较主服务器上的当前的WAL写位置与备服务器上的最新“接收/重做”的WAL位置来计算复制的延迟。它们各自可以通过在主服务器端使用pg_current_xlog_location函数来获取,在备服务器上通过pg_last_xlog_receive_location或者pg_last_xlog_replay_location来获取。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ psql ­c "SELECT pg_current_xlog_location()" ­h192.168.0.10
(primary host)
pg_current_xlog_location
0/2000000
(1 row)
$ psql ­c "select pg_last_xlog_receive_location()" ­h192.168.0.20
(standby host)
pg_last_xlog_receive_location
0/2000000
(1 row)
$ psql ­c "select pg_last_xlog_replay_location()" ­h192.168.0.20
(standby host)
pg_last_xlog_replay_location
0/2000000
(1 row)

12.其他检查流复制的方法有:最简单的方法是在备服务器上执行“select now()-pg_last_xact_replay_timestamp();”。pg_last_xact_replay_timestamp()函数给出在恢复期间最近的事务重做的时间戳,这些是在主服务器产生事务产生的提交或中止WAL记录的时间。如果在恢复期间没有事务重做,这个函数就会返回NULL。否则,如果恢复仍然在进行的话,它会一直递增。如果恢复已经完成,这时的值会保留在恢复期间中最近事务重做的值而不会变。当服务器已经正常启动并没有恢复,这个函数就返回NULL.你可以尝试在主服务器上做一些操作,然后检查这个函数的输出。
如果你想手工检查主备之间的延迟,那可以做以下步骤:

1
2
3
4
5
6
7
8
9
10
11
步骤1:在主服务器上使用以下命令来创建表。
create table stream_delay (tstamp timestamp without time zone );
insert into stream_delay select now();
步骤2: 在主服务器上使用调度工具cronjob每分钟执行以下命令。
update stream_delay set tstamp='now()';
步骤3: 通过在备服务器上检索"stream_delay"表来证实延迟。
它应该显示在主服务器上最近更新的时间。这个时间戳和备服务器的当前时间戳之差就是主服务器和备服务器之间的延迟。

你也可以通过使用ps命令来检查流复制的进展。显示的”LSNs”位置指明了备服务器已经写到了xlog的字节位置。

1
2
3
4
5
6
7
[primary] $ ps ­ef | grep sender
postgres 6879 6831 0 10:31 ? 00:00:00 postgres: wal sender
process postgres 127.0.0.1(44663) streaming 0/2000000
[standby] $ ps ­ef | grep receiver
postgres 6878 6872 1 10:31 ? receiver process streaming 0/2000000

谢谢大家,请让我知道我是否遗漏了什么。