搭建基于流复制 PostgreSQL 主备容器集群
概述
PostgreSQL 内置提供了基于流复制实现主备集群能力,使用场景:
- 防单点故障
- 读写分离提升 I/O 性能
流复制集群包含:
- 主节点 primary server:提供读写
- 备节点 standby server:提供只读查询;备节点在主故障时也可以提升为主
组成物理复制(physical replication)主备节点要求
select version()输出版本号为中major.minormajor 要一致,如16.1和16.2两个节点可以同步,14.1和16.1不可以- 节点机器同架构,32 位和 32 位可以,64 位和 64 位可以,32 和 64 位不可以。
注:如果想不同版本和架构节点间同步,需用 Logical Replication (逻辑复制) .
工作原理:TBD.
后面以容器环境搭建为例:
- Ubuntu LTS docker
- PostgreSQL 16.x
- 主节点主机 ip 10.0.0.1
- 备节点主机 ip 10.0.0.2
创建主节点
宿主机执行 docker pull postgres:16 下载 pg 最新镜像
生成主节点 pg 实例配置
sudo mkdir -p /data/pg1
sudo docker run -i --rm postgres:16 cat /usr/share/postgresql/postgresql.conf.sample > /data/pg1/postgresql.conf按需修改,如
# 通用配置
listen_addresses = '*'
logging_collector = on
log_directory = '/var/log/postgresql'
log_min_messages = info
log_min_duration_statement = 500
# 主备集群相关配置
wal_level = replica
max_wal_senders = 10
wal_keep_size = '1GB'
wal_compression = on创建 pg 主节点容器实例
sudo docker run \
--name pg1 \
-p 5432:5432 \
-e POSTGRES_USER=postgres \
-e POSTGRES_DB=postgres \
-e POSTGRES_PASSWORD=secret \
-e POSTGRES_HOST_AUTH_METHOD=md5 \
-e PGDATA=/var/lib/postgresql/data/pgdata \
-v /data/pg1:/var/lib/postgresql/data \
postgres:16 -c 'config_file=/var/lib/postgresql/data/postgresql.conf'参数说明
- 环境变量
POSTGRES_HOST_AUTH_METHOD主机认证方法; - 环境变量
POSTGRES_DB创建名为postgres数据库; - 环境变量
POSTGRES_USER创建名为postgres用户名 ; - 环境变量
PGDATA自定义数据存储路径 - 启动参数
-c指定主配置文件。注:当指定时它所在目录不能和PGDATA目录相同,否则会报PGDATA不为空(由于目录里面存在配置文件)初始化失败
确认服务启动成功 docker exec -it pg1 psql -h localhost -U postgres -p 5432 -d postgres -c 'select version()'
设置主节点集群相关配置
在主节点 上执行
- 创建同步账户 repl
CREATE ROLE repl login replication encrypted password 'secret'; - 按需修改 pg_hba.conf 设置权限
host replication repl 10.0.0.1/24 md5 - 应用权限配置,连接 pg 实例执行
SELECT pg_reload_conf();
在从节点或宿主机上执行,测试同步账号 PGPASSWORD="secret" psql -h localhost -p 5432 -U repl -d postgres
在主节点 pg 实例上执行,创建 replication slot
select * from pg_create_physical_replication_slot('repl01');
select slot_name, slot_type, active, wal_status from pg_replication_slots;注:slot 不支持改名,可重建 select * from pg_drop_replication_slot('repl01');
创建备节点
宿主机执行 docker pull postgres 下载 pg 最新镜像
生成备节点 pg 实例临时配置
sudo mkdir -p /data/pg2
sudo docker run -i --rm postgres cat /usr/share/postgresql/postgresql.conf.sample > /data/pg2/postgresql.conf创建 pg 备节点容器临时实例,注:临时节点指定 PGDATA 数据路径有 .tmp 后缀
sudo docker run \
--name pg2 \
-p 5433:5432 \
-e POSTGRES_USER=postgres \
-e POSTGRES_DB=postgres \
-e POSTGRES_PASSWORD=secret \
-e POSTGRES_HOST_AUTH_METHOD=md5 \
-e PGDATA=/var/lib/postgresql/data/pgdata.tmp \
-v /data/pg2:/var/lib/postgresql/data \
postgres:16 -c 'config_file=/var/lib/postgresql/data/postgresql.conf'进入 pg 备节点容器临时实例 shell,从主节点复制集群依赖数据
docker exec -it pg2 /bin/bash
PGPASSWORD=secret \
pg_basebackup \
--pgdata /var/lib/postgresql/data/pgdata \
--format=p \
--write-recovery-conf \
--checkpoint=fast \
--label=mffb \
--progress \
--host=10.0.0.1 \
--port=5433 \
--username=repl如果备节点无法访问主节点,留意主节点日志错误提示,按需修改 主认证配置文件。
示例提示错误:
2049-05-19 09:06:24.100 GMT [153] FATAL: no pg_hba.conf entry for replication connection from host "172.17.0.1", user "repl", no encryption
则修改住认证配置文件 pg_hba.conf ,补 host replication repl 172.17.0.1/32 md5 。
退出 shell 并删除临时 pg 容器实例
sudo docker stop pg2
sudo docker rm mypg2修改备节点配置
cp /data/pg2/postgresql.conf /data/pg2/postgresql.conf.bak
cp /data/pg2/pgdata/postgresql.auto.conf /data/pg2/postgresql.conf
# 以下两个文件内容可参考主节点
touch /data/pg2/pgdata/pg_ident.conf
touch /data/pg2/pgdata/pg_hba.conf修改从节点主配置文件 /data/pg2/postgresql.conf
primary_conninfo = 'user=repl port=5432 host=10.0.0.2 password=secret'
primary_slot_name = 'repl01'
listen_addresses = '*'
logging_collector = on
log_directory = '/var/log/postgresql'
log_min_messages = info
log_min_duration_statement = 500创建备节点 pg 容器实例
sudo docker run \
--name pg2 \
-p 5433:5432 \
-e POSTGRES_USER=postgres \
-e POSTGRES_DB=postgres \
-e POSTGRES_PASSWORD=secret \
-e POSTGRES_HOST_AUTH_METHOD=md5 \
-e PGDATA=/var/lib/postgresql/data/pgdata \
-v /data/pg2:/var/lib/postgresql/data \
postgres:16 -c 'config_file=/var/lib/postgresql/data/postgresql.conf'另开一终端,连接主节点上执行确认复制状态。
方法一:select slot_name, slot_type, active, wal_status from pg_replication_slots;
slot_name | slot_type | active | wal_status
-----------+-----------+--------+------------
repl01 | physical | t | reserved
(1 row)输出说明
slot_typeThe slot type: physical or logicalreservedmeans that the claimed files are within max_wal_size.activeTrue if this slot is currently actively being used
方法二:select * from pg_stat_replication;
pid | 3714690
usesysid | 16505
usename | repl
application_name | 14/main
client_addr | 10.0.0.2
client_hostname |
client_port | 47772
backend_start | 2049-01-23 20:13:24.429329+08
backend_xmin |
state | streaming
sent_lsn | 4B/E8080518
write_lsn | 4B/E8080518
flush_lsn | 4B/E8080518
replay_lsn | 4B/E8080518
write_lag |
flush_lag |
replay_lag |
sync_priority | 0
sync_state | async
reply_time | 2049-01-23 20:28:07.26646+08write_lag flush_lag replay_lag 三列字段如果为非空表示同步有延迟。
测试在主节点上插入新数据
create table t1 (id int) ;
insert into t1 (id) values (1);在备上查询 select * from t1; 确认同步正常。
注:默认备节点是只读(read-only)模式,只允许查数据不允许写入数据。
