PostgreSQL建立Hot Standby的Replication机制

PostgreSQL的Replication机制,大概有三种。

类型 用户 优点
Simply streaming replication On-prem, Manual EC2 简单设置;I/O性能高;存储量大
Replicated block device RDS, Azure Postgres 数据在云环境的耐久度高
Reconstruct from WAL
(and switch to streaming replication)replicationHeroku
Heroku Citus Cloud 节点自动重启;允许fork和点恢复

这里用的是第一种。

安装PostgreSQL

sudo apt install postgresql

Ubuntu 16.04上,PostgreSQL版本为9.5,配置文件的目录为/etc/postgresql/9.5/main/。 以下的配置文件都在此目录下。

当然,用Docker来部署也是更灵活的,需要去library/postgres - Docker Hub寻找合适的镜像。 配置文件的位置,可以在运行时指定。

master机

先去创建一个同步专用账户repl

$ sudo su - postgres
$ psql
postgres=# create user repl replication password '******';

然后修改两个配置文件。 其一是postgresql.conf

#------------------------------------------------------------------------------
# CONNECTIONS AND AUTHENTICATION
#------------------------------------------------------------------------------

# - Connection Settings -
listen_addresses = '*'                  # what IP address(es) to listen on;
port = 5432                             # (change requires restart)
max_connections = 10000                 # (change requires restart)

#------------------------------------------------------------------------------
# WRITE AHEAD LOG
#------------------------------------------------------------------------------

# - Settings -
wal_level = hot_standby                 # minimal, archive, hot_standby, or logical
synchronous_commit = local              # synchronization level;

#------------------------------------------------------------------------------
# REPLICATION
#------------------------------------------------------------------------------

# - Sending Server(s) -
max_wal_senders = 32            # max number of walsender processes
wal_keep_segments = 64          # in logfile segments, 16MB each; 0 disables

# - Master Server -
synchronous_standby_names = 'pg_standby'        # standby servers that provide sync rep
hot_standby = on                        # "on" allows queries during recovery

以上配置仅是和热备份相关的片段。 其中,'pg_standby'需要在/etc/hosts中配置为slave的IP。

其二是pg_hba.conf文件:

# TYPE  DATABASE        USER            ADDRESS                 METHOD

# IPv4 local connections:
host    all             all             127.0.0.1/32            trust
# IPv6 local connections:
host    all             all             ::1/128                 trust
# Allow replication connections from localhost, by a user with the
# replication privilege.
host    replication     repl        0.0.0.0/0        md5

最后一行就是允许repl的访问连接。

完成修改后,重启服务。

sudo systemctl restart postgresql.service

slave机

修改前,先停止服务。

sudo systemctl stop postgresql.service

先做首次备份(需要输入前面repl用户的密码):

rm -rf /var/lib/postgresql/9.5/main/
pg_basebackup -h pg_master -U repl -p 5432 -F p -P -x -R -D /var/lib/postgresql/9.5/main/ -l 20180907

然后修改一个配置,postgresql.conf

listen_addresses = 'localhost,pg_master'
port = 5432
max_connections = 10000
wal_level = hot_standby
max_wal_senders = 8
wal_keep_segments = 16
hot_standby = on

最后新增一个配置,recovery.conf

standby_mode = 'on'
primary_conninfo = 'host=pg_master port=5432 user=repl password=******** sslmode=disable sslcompression=1 application_name=pg_standby'
recovery_target_timeline = 'latest'

完成修改后,启动服务。

sudo systemctl start postgresql.service

测试

在master上建表:

$ sudo su - postgres
$ psql
postgres=# create database test;
CREATE DATABASE

然后,在slave上查看结果:

postgres=# \l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges
-----------+----------+----------+-------------+-------------+-----------------------
 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
 test      | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
(4 rows)

一些问题

端口

如果在配置时修改了默认端口5432,比如改成65432, 则需要在pg_basebackup同步时添加-p 65432参数,否则备份失败。 也需要在所有使用的地方注意,否则会找不到数据库服务。

一个错误

FATAL:  hot standby is not possible because max_connections = 100 is a lower setting than on the master server (its value was 10000)

以上是导致slave的PostgreSQL起不来的一个原因。 在postgresql.conf中,max_connections不应该小于master。 由于master设为10000,这里至少需要设为10000

一个警告

postgres=# create database test;
^CCancel request sent
WARNING:  canceling wait for synchronous replication due to user request
DETAIL:  The transaction has already committed locally, but might not have been replicated to the standby.

执行写操作时,总是无法返回;Ctrl+c取消后,又收到警告。 而slave上,明明已经同步完成。

可以通过配置postgresql.conf,修改一行解决。

synchronous_commit = local                # synchronization level;

这表示每次commit设置为仅保证本地完成,不等待远程同步。 这相当于在CAP中取AP,比较适合当前的使用场景。

参考


相关笔记