[实时数仓]玩转PostgreSQL主从流复制

2023-03-21 20:45:09 浏览数 (1)

PostgreSQL 在 9.0 以后引入了流复制(Streaming Replication)。流复制提供了将 WAL 记录连续发送并应用到从服务器以使其保持最新状态的功能。通过流复制,从服务器不断从主服务器同步相应的数据,同时,从服务器作为主服务器的一个备份。

本文主要记录 PostgreSQL 主从流复制的部署。

服务器规划

角色

地址

版本

主服务器

172.31.5.1

Ubuntu 18.04,PostgreSQL 10

从服务器

172.31.5.2

Ubuntu 18.04,PostgreSQL 10

PostgreSQL 安装

代码语言:javascript复制
# Add PostgresSQL Repository to Ubuntu
sudo sh -c "echo 'deb http://apt.postgresql.org/pub/repos/apt/ `lsb_release -c -s`-pgdg main' >> /etc/apt/sources.list.d/pgdg.list"
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
# Update and Install PostgreSQL
sudo apt-get update
sudo apt-get install -y postgresql-10
复制代码

主服务器配置

进入数据库

代码语言:javascript复制
sudo -u postgres psql

创建 replicator 用户用于登录和复制

代码语言:javascript复制
create role replicator login replication encrypted password 'password';

配置 pg_hba.conf

代码语言:javascript复制
sudo vim /etc/postgresql/10/main/pg_hba.conf

添加以下内容

代码语言:javascript复制
host all  all  172.31.0.0/16 trust  # 允许连接
host replication  replicator  172.31.0.0/16 trust # 允许replicator用户复制本机数据

配置 postgrsql.conf

代码语言:javascript复制
sudo vim /etc/postgresql/10/main/postgresql.conf

按照以下内容配置

代码语言:javascript复制
listen_addresses = '*'   #监听所有ip
archive_mode = on   #开启归档模式
archive_command = 'cp %p /var/lib/postgresql/10/main/%f'   #归档命令
wal_level = replica    # 决定多少信息写入WAL,此处为replica模式
max_wal_senders = 10   #最大流复制连接,一般和从服务相等
wal_sender_timeout = 60s    #流复制超时时间
max_connections = 100   #最大连接数,必须不大于从库的配置

重启数据库

代码语言:javascript复制
sudo service postgresql restart

从服务器配置

先测试一下能否连接主服务器

代码语言:javascript复制
psql -h 172.31.5.1 -U postgres

配置 postgresql.conf

代码语言:javascript复制
wal_level = replica    #决定多少信息写入WAL,此处为replica模式
max_connections = 300   #最大连接数,必须不小于主库的配置
hot_standby = on #说明这台机器不仅用于数据归档,还可以用于数据查询
max_standby_streaming_delay = 30s #流备份的最大延迟时间
wal_receiver_status_interval = 10s  #向主服务器汇报本机状态的间隔时间
hot_standby_feedback = on  #是否向主服务器反馈错误的数据复制

首先清空 PostgreSQL 数据

代码语言:javascript复制
sudo su - postgres  # 切换到postgresl用户
rm -rf 10/main/*  # 清空data目录数据

然后备份主服务器数据

代码语言:javascript复制
pg_basebackup -D 10/main/ -h 172.31.5.1 -U replicator -X stream -P

配置 recovery.conf

代码语言:javascript复制
vim 10/main/recovery.conf
代码语言:javascript复制
standby_mode = on    # 说明该节点是从服务器
primary_conninfo = 'host=172.31.5.1 port=5432 user=replicator password=password'  # 主服务器的连接信息
recovery_target_timeline = 'latest'

退出用户,然后重启数据库

代码语言:javascript复制
sudo service postgresql restart

验证部署

在主服务上执行,结果如下:

代码语言:javascript复制
postgres=# select client_addr,sync_state from pg_stat_replication;
 client_addr  | sync_state
-------------- ------------
 172.31.5.2 | async
(1 row)

我们也可以在两台服务器上执行 ps aux | grep postgres 来验证部署成功,可以看到

主服务器上有一个 wal sender process

从服务器上有一个 wal receiver process

测试

主服务器创建数据库:

代码语言:javascript复制
postgres=# create database test;
CREATE DATABASE
postgres=# l
                              List of databases
   Name    |  Owner   | Encoding | Collate |  Ctype  |   Access privileges
----------- ---------- ---------- --------- --------- -----------------------
 postgres  | postgres | UTF8     | C.UTF-8 | C.UTF-8 |
 template0 | postgres | UTF8     | C.UTF-8 | C.UTF-8 | =c/postgres           
           |          |          |         |         | postgres=CTc/postgres
 template1 | postgres | UTF8     | C.UTF-8 | C.UTF-8 | =c/postgres           
           |          |          |         |         | postgres=CTc/postgres
 test      | postgres | UTF8     | C.UTF-8 | C.UTF-8 |
(4 rows)

此时从服务器可以同步看到

代码语言:javascript复制
postgres=# l
                              List of databases
   Name    |  Owner   | Encoding | Collate |  Ctype  |   Access privileges
----------- ---------- ---------- --------- --------- -----------------------
 postgres  | postgres | UTF8     | C.UTF-8 | C.UTF-8 |
 template0 | postgres | UTF8     | C.UTF-8 | C.UTF-8 | =c/postgres           
           |          |          |         |         | postgres=CTc/postgres
 template1 | postgres | UTF8     | C.UTF-8 | C.UTF-8 | =c/postgres           
           |          |          |         |         | postgres=CTc/postgres
 test      | postgres | UTF8     | C.UTF-8 | C.UTF-8 |
(4 rows)

如果我们在从服务器上执行:

代码语言:javascript复制
postgres=# drop database test;
ERROR:  cannot execute DROP DATABASE in a read-only transaction

可以看到无法在从服务器上执行写操作,因为从服务器是只读的。

这样我们就完成了主从流复制的部署和验证测试。

0 人点赞