一、Pgpool-II + PostgreSQL 高可用方案介绍

核心能力
|------------|--------------------------------------------------------|
| 能力 | 实现方式 |
| 读写分离 | Pgpool load_balance_mode = on,读请求分发到从节点 |
| 连接池 | num_init_children = 32,max_pool = 5,复用连接 |
| 故障检测 | health_check_period = 10,每10秒检测后端节点状态 |
| 自动故障转移 | failover_on_backend_shutdown = on,主节点宕机时 Pgpool 自动切换 |
| 自动恢复 | PGPOOL_AUTO_FAILBACK=yes,节点恢复后自动加入集群 |
| 高可用 | PostgreSQL 通过 repmgr 实现流复制 + 自动主从切换 |
架构说明
1. PostgreSQL 层(repmgr 流复制)
-
3个节点:pg-0(主)、pg-1(从)、pg-2(从)
-
使用
bitnami/postgresql-repmgr镜像,内置 repmgr 扩展 -
POSTGRESQL_SHARED_PRELOAD_LIBRARIES=repmgr启用 repmgr -
repmgr 负责:流复制管理、主从选举、自动故障转移
2. Pgpool-II 层(中间件)
-
监听
:9999,应用连接 Pgpool 而非直连 PostgreSQL -
backend_clustering_mode = 'streaming_replication'--- 流复制模式 -
自动感知主从:通过
sr_check_user = 'repmgr'检测各节点角色 -
写请求 → 主节点,读请求 → 负载均衡到所有节点
-
主节点故障时,repmgr 选举新主,Pgpool 自动感知并切换
二、部署过程
1.环境准备
|----------|---------------|---------------------------|-----------------------------|
| 主机名 | ip | 操作系统 | 备注 |
| master01 | 192.168.48.80 | openEuler 24.03 (LTS-SP2) | docker、postgresql主节点、pgpool |
| node01 | 192.168.48.81 | openEuler 24.03 (LTS-SP2) | docker、postgresql从节点1 |
| node02 | 192.168.48.82 | openEuler 24.03 (LTS-SP2) | docker、postgresql从节点2 |
2.Postgresql
master01
.env
绝对路径:/root/pg-cluster/postgresql/.env
# PostgreSQL 数据库配置
# PostgreSQL 超级用户密码
POSTGRESQL_POSTGRES_PASSWORD=postgres
# 应用用户配置
POSTGRESQL_USERNAME=mydiy
POSTGRESQL_PASSWORD=mydiy
POSTGRESQL_DATABASE=mydiy
# repmgr 配置
REPMGR_USERNAME=repmgr
REPMGR_PASSWORD=repmgr
REPMGR_DATABASE=repmgr
# 备份服务配置(使用 POSTGRES_ 前缀,与图片中的变量名一致)
POSTGRES_DB=flygpt
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_HOST=localhost # host模式使用(如需要可取消注释)
POSTGRES_PORT=5432 # host模式使用(如需要可取消注释)
BACKUP_DIR=/backups
RETENTION_DAYS=7
# 时区配置
TZ=Asia/Shanghai
custom.conf
postgresql默认会自己生成配置文件,这里指定自定义custom.conf文件为配置文件
绝对路径:/data/postgresql/conf.d/custom.conf
# PostgreSQL 配置文件 - 分类整理版本
# 1. 网络与连接配置
# 网络监听设置
listen_addresses = '*' # 监听所有网络接口
port = 5432 # 监听端口(更改需要重启)
# 连接限制
max_connections = 300 # 最大连接数(更改需要重启)
# 2. 内存配置
# 共享内存设置
shared_buffers = 3GB # 共享缓冲区大小,最小128kB(更改需要重启)
# 工作内存设置
work_mem = 16MB # 每个操作的工作内存,最小64kB
maintenance_work_mem = 8GB # 维护操作的工作内存
# 缓存配置
effective_cache_size = 8GB # 操作系统和磁盘缓存的有效大小
# 3. 并行处理配置
# 并行工作进程
max_worker_processes = 10 # 最大工作进程数(更改需要重启)
max_parallel_workers = 8 # 最大并行工作进程数
# 并行查询配置
max_parallel_workers_per_gather = 4 # 每个Gather节点的最大并行工作进程
# 4. 预写日志(WAL)配置
# WAL缓冲区设置
wal_buffers = 64MB # WAL缓冲区大小,最小32kB(更改需要重启)
# WAL文件大小限制
max_wal_size = 2GB # 最大WAL大小
min_wal_size = 160MB # 最小WAL大小
# 5. 检查点配置
checkpoint_completion_target = 0.9 # 检查点目标持续时间,0.0 - 1.0
# 6. 查询优化配置
# 成本估算参数
random_page_cost = 1.1 # 随机页面访问成本(SSD建议1.0-1.5)
# 统计信息配置
default_statistics_target = 500 # 默认统计目标,范围1-10000
# 7. 自动清理配置
# 自动清理工作进程
autovacuum_max_workers = 4 # 自动清理子进程的最大数量
# 自动清理性能调整
autovacuum_vacuum_cost_delay = 10ms # 自动清理的成本延迟,以毫秒为单位
#密码加密方式
password_encryption = scram-sha-256
wal_log_hints = on
logging_collector = on
archive_mode = on
docker-compose.yaml
/root/pg-cluster/postgresql/docker-compose.yaml
# PostgreSQL 主节点 docker-compose.yaml(部署在master01节点:192.168.48.80)
services:
# PostgreSQL 主节点配置
pg-0:
image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/bitnami/postgresql-repmgr:17.5.0-debian-12-r7
container_name: pg-0
restart: unless-stopped # 改为 unless-stopped,避免异常时无限重启
stop_grace_period: 60s # 给 PostgreSQL 60 秒优雅停止时间
stop_signal: SIGTERM # 使用 SIGTERM 信号优雅停止
network_mode: "host" # 使用主机网络模式,容器直接使用主机网络栈,便于节点间通信
volumes:
- pg_data:/bitnami/postgresql # PostgreSQL 数据目录持久化
- /data/postgresql/conf.d:/opt/bitnami/postgresql/conf/conf.d:ro # 挂载自定义配置文件目录(只读)
- /etc/localtime:/etc/localtime:ro # 同步主机时区
environment:
# PostgreSQL 基本配置(从 .env 文件读取)
- POSTGRESQL_POSTGRES_PASSWORD=${POSTGRESQL_POSTGRES_PASSWORD} # PostgreSQL 超级用户 postgres 的密码
# 创建应用用户 flydiy
- POSTGRESQL_USERNAME=${POSTGRESQL_USERNAME}
# 设置应用用户密码
- POSTGRESQL_PASSWORD=${POSTGRESQL_PASSWORD}
# 创建应用数据库
- POSTGRESQL_DATABASE=${POSTGRESQL_DATABASE}
# repmgr 必要认证配置(从 .env 文件读取)
- REPMGR_USERNAME=${REPMGR_USERNAME} # repmgr 管理用户
- REPMGR_PASSWORD=${REPMGR_PASSWORD} # repmgr 用户密码
- REPMGR_DATABASE=${REPMGR_DATABASE} # repmgr 元数据数据库
# 时区配置
- TZ=${TZ}
# repmgr 集群配置 - 主节点特定配置
- REPMGR_NODE_ID=1 # 当前节点在集群中的唯一标识符
- REPMGR_USE_SUPERUSER=yes # 允许 repmgr 使用超级用户权限执行管理操作
- REPMGR_NODE_NAME=pg-0 # 节点在集群中的逻辑名称
- REPMGR_NODE_NETWORK_NAME=192.168.48.80 # 节点对外提供服务的网络地址
- REPMGR_PRIMARY_HOST=192.168.48.80 # 初始主节点地址(启动时指向自己)
- REPMGR_PRIMARY_PORT=5432 # 主节点端口
- REPMGR_PARTNER_NODES=192.168.48.80:5432,192.168.48.81:5432,192.168.48.82:5432 # 集群中所有节点的地址列表
- REPMGR_PORT_NUMBER=5432 # 当前节点监听端口
# 流复制关键配置
- POSTGRESQL_WAL_LEVEL=replica # WAL日志级别设置为副本,支持流复制
- POSTGRESQL_MAX_WAL_SENDERS=10 # 最大WAL发送进程数,限制可连接的备用节点数量
- POSTGRESQL_MAX_REPLICATION_SLOTS=10 # 最大复制槽数量,用于跟踪备用节点状态
- POSTGRESQL_SHARED_PRELOAD_LIBRARIES=repmgr # 预加载 repmgr 扩展
# 主节点初始化配置
- REPMGR_INIT_PRIMARY=true # 将该节点初始化为集群的主节点
- REPMGR_CREATE_MASTER_RECORD=true # 在 repmgr 元数据中创建主节点记录
- BITNAMI_DEBUG=true # 启用 Bitnami 镜像的调试日志输出
# 同步提交配置(可选,提高数据一致性但可能影响性能)
#- POSTGRESQL_SYNCHRONOUS_COMMIT=on # 启用同步提交,确保事务在多个节点确认后才返回
#- POSTGRESQL_SYNCHRONOUS_STANDBY_NAMES=* # 指定所有备用节点为同步副本
# 测试环境使用,生产环境建议关闭(允许所有连接无需密码验证)
#- REPMGR_PGHBA_TRUST_ALL=yes
# 内存优化配置
- POSTGRESQL_MAINTENANCE_WORK_MEM=1GB # 维护操作(如VACUUM、索引创建)可用的内存大小
# 多数据库vector扩展自动安装
- POSTGRESQL_EXTRA_INIT_SCRIPTS=/opt/bitnami/scripts/postgresql/multi-db-vector-setup.sh
# 添加主机名映射
extra_hosts:
- "pg-0:192.168.48.80"
- "pg-1:192.168.48.81"
- "pg-2:192.168.48.82"
# 健康检查配置
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d postgres || exit 1"]
interval: 10s # 每 10 秒检查一次
timeout: 5s # 超时时间 5 秒
retries: 5 # 失败 5 次后标记为 unhealthy
start_period: 60s # 启动后 60 秒才开始健康检查
# 定义持久化卷
volumes:
pg_data:
driver: local
driver_opts:
type: none
o: bind
device: /data/postgresql # 将主机的 /data/postgresql 目录绑定挂载为数据卷
node01
.env
绝对路径:/root/pg-cluster/postgresql/.env
# PostgreSQL 数据库配置
# PostgreSQL 超级用户密码
POSTGRESQL_POSTGRES_PASSWORD=postgres
# 应用用户配置
POSTGRESQL_USERNAME=mydiy
POSTGRESQL_PASSWORD=mydiy
POSTGRESQL_DATABASE=mydiy
# repmgr 配置
REPMGR_USERNAME=repmgr
REPMGR_PASSWORD=repmgr
REPMGR_DATABASE=repmgr
# 备份服务配置(使用 POSTGRES_ 前缀,与图片中的变量名一致)
POSTGRES_DB=flygpt
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_HOST=localhost # host模式使用(如需要可取消注释)
POSTGRES_PORT=5432 # host模式使用(如需要可取消注释)
BACKUP_DIR=/backups
RETENTION_DAYS=7
# 时区配置
TZ=Asia/Shanghai
custom.conf
postgresql默认会自己生成配置文件,这里指定自定义custom.conf文件为配置文件
绝对路径:/data/postgresql/conf.d/custom.conf
# PostgreSQL 配置文件 - 分类整理版本
# 1. 网络与连接配置
# 网络监听设置
listen_addresses = '*' # 监听所有网络接口
port = 5432 # 监听端口(更改需要重启)
# 连接限制
max_connections = 300 # 最大连接数(更改需要重启)
# 2. 内存配置
# 共享内存设置
shared_buffers = 3GB # 共享缓冲区大小,最小128kB(更改需要重启)
# 工作内存设置
work_mem = 16MB # 每个操作的工作内存,最小64kB
maintenance_work_mem = 8GB # 维护操作的工作内存
# 缓存配置
effective_cache_size = 8GB # 操作系统和磁盘缓存的有效大小
# 3. 并行处理配置
# 并行工作进程
max_worker_processes = 10 # 最大工作进程数(更改需要重启)
max_parallel_workers = 8 # 最大并行工作进程数
# 并行查询配置
max_parallel_workers_per_gather = 4 # 每个Gather节点的最大并行工作进程
# 4. 预写日志(WAL)配置
# WAL缓冲区设置
wal_buffers = 64MB # WAL缓冲区大小,最小32kB(更改需要重启)
# WAL文件大小限制
max_wal_size = 2GB # 最大WAL大小
min_wal_size = 160MB # 最小WAL大小
# 5. 检查点配置
checkpoint_completion_target = 0.9 # 检查点目标持续时间,0.0 - 1.0
# 6. 查询优化配置
# 成本估算参数
random_page_cost = 1.1 # 随机页面访问成本(SSD建议1.0-1.5)
# 统计信息配置
default_statistics_target = 500 # 默认统计目标,范围1-10000
# 7. 自动清理配置
# 自动清理工作进程
autovacuum_max_workers = 4 # 自动清理子进程的最大数量
# 自动清理性能调整
autovacuum_vacuum_cost_delay = 10ms # 自动清理的成本延迟,以毫秒为单位
#密码加密方式
password_encryption = scram-sha-256
wal_log_hints = on
logging_collector = on
archive_mode = on
docker-compose.yaml
/root/pg-cluster/postgresql/docker-compose.yaml
# PostgreSQL 备用节点 docker-compose.yaml(部署在node01:192.168.48.81)
services:
# PostgreSQL 备用节点配置
pg-1:
image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/bitnami/postgresql-repmgr:17.5.0-debian-12-r7
container_name: pg-1
restart: unless-stopped # 改为 unless-stopped,避免异常时无限重启
stop_grace_period: 60s # 给 PostgreSQL 60 秒优雅停止时间
stop_signal: SIGTERM # 使用 SIGTERM 信号优雅停止
network_mode: "host" # 使用主机网络模式,便于节点间直接通信
volumes:
- pg_data:/bitnami/postgresql # 备用节点数据目录持久化
- /data/postgresql/conf.d:/opt/bitnami/postgresql/conf/conf.d:ro # 挂载自定义配置文件目录(只读)
environment:
# PostgreSQL 基本配置(从 .env 文件读取)
- POSTGRESQL_POSTGRES_PASSWORD=${POSTGRESQL_POSTGRES_PASSWORD} # PostgreSQL 超级用户 postgres 的密码
# 创建应用用户 flydiy
- POSTGRESQL_USERNAME=${POSTGRESQL_USERNAME}
# 设置应用用户密码
- POSTGRESQL_PASSWORD=${POSTGRESQL_PASSWORD}
# 创建应用数据库
- POSTGRESQL_DATABASE=${POSTGRESQL_DATABASE}
# repmgr 必要认证配置(从 .env 文件读取)
- REPMGR_USERNAME=${REPMGR_USERNAME} # repmgr 管理用户
- REPMGR_PASSWORD=${REPMGR_PASSWORD} # repmgr 用户密码
- REPMGR_DATABASE=${REPMGR_DATABASE} # repmgr 元数据数据库
# repmgr 集群配置 - 备用节点特定配置
- REPMGR_NODE_ID=2 # 当前节点在集群中的唯一标识符
- REPMGR_USE_SUPERUSER=yes # 允许 repmgr 使用超级用户权限执行管理操作
- REPMGR_NODE_NAME=pg-1 # 节点在集群中的逻辑名称
- REPMGR_NODE_NETWORK_NAME=192.168.48.81 # 节点对外提供服务的网络地址
- REPMGR_PRIMARY_HOST=192.168.48.80 # 指向主节点地址,用于初始复制连接
- REPMGR_PRIMARY_PORT=5432 # 主节点端口
- REPMGR_PARTNER_NODES=192.168.48.80:5432,192.168.48.81:5432,192.168.48.82:5432 # 集群中所有节点的地址列表
- REPMGR_PORT_NUMBER=5432 # 当前节点监听端口
# 流复制配置
- POSTGRESQL_WAL_LEVEL=replica
- POSTGRESQL_MAX_WAL_SENDERS=10
- POSTGRESQL_MAX_REPLICATION_SLOTS=10
- POSTGRESQL_SHARED_PRELOAD_LIBRARIES=repmgr
# 从节点配置
- REPMGR_INIT_PRIMARY=false
- REPMGR_CREATE_MASTER_RECORD=false
- BITNAMI_DEBUG=true
# 测试环境使用,生产环境建议关闭(允许所有连接无需密码验证)
#- REPMGR_PGHBA_TRUST_ALL=yes
# 优化配置
- POSTGRESQL_MAINTENANCE_WORK_MEM=1GB # 维护操作可用的内存大小
# 添加主机名映射
extra_hosts:
- "pg-0:192.168.48.80"
- "pg-1:192.168.48.81"
- "pg-2:192.168.48.82"
# 健康检查配置
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d postgres || exit 1"]
interval: 10s # 每 10 秒检查一次
timeout: 5s # 超时时间 5 秒
retries: 5 # 失败 5 次后标记为 unhealthy
start_period: 60s # 启动后 60 秒才开始健康检查
# 定义持久化卷
volumes:
pg_data:
driver: local
driver_opts:
type: none
o: bind
device: /data/postgresql # 将主机的 /data/postgresql 目录绑定挂载为数据卷
node02
.env
绝对路径:/root/pg-cluster/postgresql/.env
# PostgreSQL 数据库配置
# PostgreSQL 超级用户密码
POSTGRESQL_POSTGRES_PASSWORD=postgres
# 应用用户配置
POSTGRESQL_USERNAME=mydiy
POSTGRESQL_PASSWORD=mydiy
POSTGRESQL_DATABASE=mydiy
# repmgr 配置
REPMGR_USERNAME=repmgr
REPMGR_PASSWORD=repmgr
REPMGR_DATABASE=repmgr
# 备份服务配置(使用 POSTGRES_ 前缀,与图片中的变量名一致)
POSTGRES_DB=flygpt
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_HOST=localhost # host模式使用(如需要可取消注释)
POSTGRES_PORT=5432 # host模式使用(如需要可取消注释)
BACKUP_DIR=/backups
RETENTION_DAYS=7
# 时区配置
TZ=Asia/Shanghai
custom.conf
postgresql默认会自己生成配置文件,这里指定自定义custom.conf文件为配置文件
绝对路径:/data/postgresql/conf.d/custom.conf
# PostgreSQL 配置文件 - 分类整理版本
# 1. 网络与连接配置
# 网络监听设置
listen_addresses = '*' # 监听所有网络接口
port = 5432 # 监听端口(更改需要重启)
# 连接限制
max_connections = 300 # 最大连接数(更改需要重启)
# 2. 内存配置
# 共享内存设置
shared_buffers = 3GB # 共享缓冲区大小,最小128kB(更改需要重启)
# 工作内存设置
work_mem = 16MB # 每个操作的工作内存,最小64kB
maintenance_work_mem = 8GB # 维护操作的工作内存
# 缓存配置
effective_cache_size = 8GB # 操作系统和磁盘缓存的有效大小
# 3. 并行处理配置
# 并行工作进程
max_worker_processes = 10 # 最大工作进程数(更改需要重启)
max_parallel_workers = 8 # 最大并行工作进程数
# 并行查询配置
max_parallel_workers_per_gather = 4 # 每个Gather节点的最大并行工作进程
# 4. 预写日志(WAL)配置
# WAL缓冲区设置
wal_buffers = 64MB # WAL缓冲区大小,最小32kB(更改需要重启)
# WAL文件大小限制
max_wal_size = 2GB # 最大WAL大小
min_wal_size = 160MB # 最小WAL大小
# 5. 检查点配置
checkpoint_completion_target = 0.9 # 检查点目标持续时间,0.0 - 1.0
# 6. 查询优化配置
# 成本估算参数
random_page_cost = 1.1 # 随机页面访问成本(SSD建议1.0-1.5)
# 统计信息配置
default_statistics_target = 500 # 默认统计目标,范围1-10000
# 7. 自动清理配置
# 自动清理工作进程
autovacuum_max_workers = 4 # 自动清理子进程的最大数量
# 自动清理性能调整
autovacuum_vacuum_cost_delay = 10ms # 自动清理的成本延迟,以毫秒为单位
#密码加密方式
password_encryption = scram-sha-256
wal_log_hints = on
logging_collector = on
archive_mode = on
docker-compose.yaml
/root/pg-cluster/postgresql/docker-compose.yaml
# PostgreSQL 备用节点 docker-compose.yaml(部署在node02:192.168.48.82)
services:
# PostgreSQL 备用节点配置
pg-2:
image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/bitnami/postgresql-repmgr:17.5.0-debian-12-r7
container_name: pg-2
restart: unless-stopped # 改为 unless-stopped,避免异常时无限重启
stop_grace_period: 60s # 给 PostgreSQL 60 秒优雅停止时间
stop_signal: SIGTERM # 使用 SIGTERM 信号优雅停止
network_mode: "host" # 使用主机网络模式,便于节点间直接通信
volumes:
- pg_data:/bitnami/postgresql # 备用节点数据目录持久化
- /data/postgresql/conf.d:/opt/bitnami/postgresql/conf/conf.d:ro # 挂载自定义配置文件目录(只读)
environment:
# PostgreSQL 基本配置(从 .env 文件读取)
- POSTGRESQL_POSTGRES_PASSWORD=${POSTGRESQL_POSTGRES_PASSWORD} # PostgreSQL 超级用户 postgres 的密码
# 创建应用用户 flydiy
- POSTGRESQL_USERNAME=${POSTGRESQL_USERNAME}
# 设置应用用户密码
- POSTGRESQL_PASSWORD=${POSTGRESQL_PASSWORD}
# 创建应用数据库
- POSTGRESQL_DATABASE=${POSTGRESQL_DATABASE}
# repmgr 必要认证配置(从 .env 文件读取)
- REPMGR_USERNAME=${REPMGR_USERNAME} # repmgr 管理用户
- REPMGR_PASSWORD=${REPMGR_PASSWORD} # repmgr 用户密码
- REPMGR_DATABASE=${REPMGR_DATABASE} # repmgr 元数据数据库
# repmgr 集群配置 - 备用节点特定配置
- REPMGR_NODE_ID=3 # 当前节点在集群中的唯一标识符
- REPMGR_USE_SUPERUSER=yes # 允许 repmgr 使用超级用户权限执行管理操作
- REPMGR_NODE_NAME=pg-2 # 节点在集群中的逻辑名称
- REPMGR_NODE_NETWORK_NAME=192.168.48.82 # 节点对外提供服务的网络地址
- REPMGR_PRIMARY_HOST=192.168.48.80 # 指向主节点地址,用于初始复制连接
- REPMGR_PRIMARY_PORT=5432 # 主节点端口
- REPMGR_PARTNER_NODES=192.168.48.80:5432,192.168.48.81:5432,192.168.48.82:5432 # 集群中所有节点的地址列表
- REPMGR_PORT_NUMBER=5432 # 当前节点监听端口
# 流复制配置
- POSTGRESQL_WAL_LEVEL=replica
- POSTGRESQL_MAX_WAL_SENDERS=10
- POSTGRESQL_MAX_REPLICATION_SLOTS=10
- POSTGRESQL_SHARED_PRELOAD_LIBRARIES=repmgr
# 从节点配置
- REPMGR_INIT_PRIMARY=false
- REPMGR_CREATE_MASTER_RECORD=false
- BITNAMI_DEBUG=true
# 测试环境使用,生产环境建议关闭(允许所有连接无需密码验证)
#- REPMGR_PGHBA_TRUST_ALL=yes
# 优化配置
- POSTGRESQL_MAINTENANCE_WORK_MEM=1GB # 维护操作可用的内存大小
# 添加主机名映射
extra_hosts:
- "pg-0:192.168.48.80"
- "pg-1:192.168.48.81"
- "pg-2:192.168.48.82"
# 健康检查配置
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d postgres || exit 1"]
interval: 10s # 每 10 秒检查一次
timeout: 5s # 超时时间 5 秒
retries: 5 # 失败 5 次后标记为 unhealthy
start_period: 60s # 启动后 60 秒才开始健康检查
# 定义持久化卷
volumes:
pg_data:
driver: local
driver_opts:
type: none
o: bind
device: /data/postgresql # 将主机的 /data/postgresql 目录绑定挂载为数据卷
3.Pgpool
只在master01节点
.env
绝对路径:/root/pg-cluster/pgpool/.env
# Pgpool 环境变量配置文件
# 仅包含敏感信息(账号密码等)
# 请妥善保管,不要提交到版本控制系统
# 流复制检查用户和密码
PGPOOL_SR_CHECK_USER=repmgr
PGPOOL_SR_CHECK_PASSWORD=repmgr
# PostgreSQL 连接用户和密码
PGPOOL_POSTGRES_USERNAME=postgres
PGPOOL_POSTGRES_PASSWORD=postgres
# 管理员用户和密码
PGPOOL_ADMIN_USERNAME=postgres
PGPOOL_ADMIN_PASSWORD=postgres
# Pgpool 加密密钥(用于 pool_passwd 加密)
PGPOOL_AES_KEY=ioZQerApstxyMU0Qx0lT98jQWSM=
# 健康检查用户和密码
PGPOOL_HEALTH_CHECK_USER=repmgr
PGPOOL_HEALTH_CHECK_PASSWORD=repmgr
pgpool.conf
绝对路径:/root/pg-cluster/pgpool/pgpool.conf
# --------------------------------
# Pgpool-II 4.6 configuration file
# --------------------------------
#------------------------------------------------------------------------------
# BACKEND CLUSTERING MODE
#------------------------------------------------------------------------------
backend_clustering_mode = 'streaming_replication'
#------------------------------------------------------------------------------
# CONNECTIONS
#------------------------------------------------------------------------------
listen_addresses = '*'
port = 9999
unix_socket_directories = '/opt/bitnami/pgpool/tmp'
pcp_listen_addresses = '*'
pcp_port = 9898
pcp_socket_dir = '/opt/bitnami/pgpool/tmp'
backend_hostname0 = '192.168.48.80'
backend_port0 = 5432
backend_weight0 = 1
backend_flag0 = 'ALLOW_TO_FAILOVER'
backend_hostname1 = '192.168.48.81'
backend_port1 = 5432
backend_weight1 = 1
backend_flag1 = 'ALLOW_TO_FAILOVER'
backend_hostname2 = '192.168.48.82'
backend_port2 = 5432
backend_weight2 = 1
backend_flag2 = 'ALLOW_TO_FAILOVER'
backend_application_name0 = 'pg-0'
backend_application_name1 = 'pg-1'
backend_application_name2 = 'pg-2'
enable_pool_hba = on
pool_passwd = 'pool_passwd'
authentication_timeout = 30
allow_clear_text_frontend_auth = on
#------------------------------------------------------------------------------
# POOLS
#------------------------------------------------------------------------------
num_init_children = 32
max_pool = 5
child_life_time = 300
#------------------------------------------------------------------------------
# LOGS
#------------------------------------------------------------------------------
log_destination = 'stderr'
log_connections = off
log_hostname = off
log_per_node_statement = off
logging_collector = on
log_directory = '/tmp/pgpool_logs'
log_filename = 'pgpool-%Y-%m-%d_%H%M%S.log'
log_truncate_on_rotation = on
log_rotation_age = '1d'
log_rotation_size = '10MB'
#------------------------------------------------------------------------------
# FILE LOCATIONS
#------------------------------------------------------------------------------
pid_file_name = '/opt/bitnami/pgpool/tmp/pgpool.pid'
logdir = '/opt/bitnami/pgpool/logs'
#------------------------------------------------------------------------------
# LOAD BALANCING MODE
#------------------------------------------------------------------------------
load_balance_mode = on
disable_load_balance_on_write = 'transaction'
statement_level_load_balance = off
#------------------------------------------------------------------------------
# STREAMING REPLICATION MODE
#------------------------------------------------------------------------------
sr_check_period = 30
sr_check_user = 'repmgr'
sr_check_password = ''
sr_check_database = 'postgres'
#------------------------------------------------------------------------------
# HEALTH CHECK GLOBAL PARAMETERS
#------------------------------------------------------------------------------
health_check_period = 10
health_check_timeout = 30
health_check_user = 'repmgr'
health_check_password = ''
health_check_max_retries = 3
health_check_retry_delay = 2
connect_timeout = 10000
#------------------------------------------------------------------------------
# FAILOVER AND FAILBACK
#------------------------------------------------------------------------------
failover_command = 'echo ">>> Failover - that will initialize new primary node search!"'
failover_on_backend_error = off
failover_on_backend_shutdown = on
search_primary_node_timeout = 0
#------------------------------------------------------------------------------
# ONLINE RECOVERY
#------------------------------------------------------------------------------
recovery_user = 'postgres'
recovery_password = ''
pool_hba.conf
绝对路径:/root/pg-cluster/pgpool/pool_hba.conf
local all all trust
host all repmgr all scram-sha-256
host all postgres all scram-sha-256
host all all all scram-sha-256
docker-compose.yaml
绝对路径:/root/pg-cluster/pgpool/docker-compose.yaml
services:
pgpool-0:
image: swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/bitnami/pgpool:4.6.2-debian-12-r1
container_name: pgpool-0
restart: always
network_mode: "host"
volumes:
# 挂载需要持久化的子目录
- pgpool_data:/opt/bitnami/pgpool/data
- pgpool_logs:/opt/bitnami/pgpool/logs
#- pgpool_conf:/opt/bitnami/pgpool/conf
# 挂载配置文件(只读挂载)
- ./pgpool.conf:/opt/bitnami/pgpool/conf.default/pgpool.conf:ro
- ./pool_hba.conf:/opt/bitnami/pgpool/conf.default/pool_hba.conf:ro
#- ./pgpool_node_id:/opt/bitnami/pgpool/conf/pgpool_node_id:ro
env_file:
- .env
environment:
# pgpool 基础配置
- PGPOOL_PORT_NUMBER=9999
- PGPOOL_BACKEND_NODES=0:192.168.48.80:5432,1:192.168.48.81:5432,2:192.168.48.82:5432
- PGPOOL_BACKEND_APPLICATION_NAMES=pg-0,pg-1,pg-2
#- PGPOOL_NODE_ID=0
# 认证配置(从 .env 文件读取敏感信息)
- PGPOOL_SR_CHECK_USER=${PGPOOL_SR_CHECK_USER}
- PGPOOL_SR_CHECK_PASSWORD=${PGPOOL_SR_CHECK_PASSWORD}
- PGPOOL_POSTGRES_USERNAME=${PGPOOL_POSTGRES_USERNAME}
- PGPOOL_POSTGRES_PASSWORD=${PGPOOL_POSTGRES_PASSWORD}
- PGPOOL_ADMIN_USERNAME=${PGPOOL_ADMIN_USERNAME}
- PGPOOL_ADMIN_PASSWORD=${PGPOOL_ADMIN_PASSWORD}
# 功能开关
- PGPOOL_ENABLE_LOAD_BALANCING=yes
- PGPOOL_ENABLE_STATEMENT_LOAD_BALANCING=no
- PGPOOL_DISABLE_LOAD_BALANCE_ON_WRITE=transaction
- PGPOOL_ENABLE_CONNECTION_CACHE=yes
- PGPOOL_STREAMING_REPLICATION=yes
- PGPOOL_REPLICATION_MODE=no
- PGPOOL_PARALLEL_MODE=no
# 连接池和超时配置
- PGPOOL_NUM_INIT_CHILDREN=32
- PGPOOL_MAX_POOL=5
- PGPOOL_CHILD_LIFE_TIME=300
- PGPOOL_TIMEOUT=360
- PGPOOL_CONNECT_TIMEOUT=10000
# 健康检查配置
- PGPOOL_HEALTH_CHECK_USER=${PGPOOL_HEALTH_CHECK_USER}
- PGPOOL_HEALTH_CHECK_PASSWORD=${PGPOOL_HEALTH_CHECK_PASSWORD}
- PGPOOL_HEALTH_CHECK_PERIOD=10
- PGPOOL_HEALTH_CHECK_TIMEOUT=30
- PGPOOL_HEALTH_CHECK_MAX_RETRIES=3
- PGPOOL_HEALTH_CHECK_RETRY_DELAY=2
- PGPOOL_HEALTH_CHECK_PSQL_TIMEOUT=15
- PGPOOL_AUTO_FAILBACK=yes
- BITNAMI_DEBUG=true
# 认证方式配置
- PGPOOL_ENABLE_POOL_HBA=yes
- PGPOOL_ENABLE_POOL_PASSWD=yes
- PGPOOL_AUTHENTICATION_METHOD=scram-sha-256
- PGPOOL_AES_KEY=${PGPOOL_AES_KEY}
# 自定义配置文件
- PGPOOL_USER_CONF_FILE=/opt/bitnami/pgpool/conf.default/pgpool.conf # 自定义 Pgpool-II 配置文件
- PGPOOL_USER_HBA_FILE=/opt/bitnami/pgpool/conf.default/pool_hba.conf # 自定义基于主机的身份验证配置
#- PGPOOL_PASSWD_FILE=pool_passwd # Pgpool-II 池密码文件
# TLS/SSL 安全配置
#- PGPOOL_ENABLE_TLS=no # 是否为流量启用 TLS
#- PGPOOL_TLS_CERT_FILE # 包含 TLS 证书的文件
#- PGPOOL_TLS_KEY_FILE # 包含证书密钥的文件
#- PGPOOL_TLS_CA_FILE # 包含证书 CA 的文件
#- PGPOOL_TLS_PREFER_SERVER_CIPHERS=yes # 使用服务器的 TLS 密码偏好
# 健康检查(修正缩进)
healthcheck:
test: ["CMD", "/opt/bitnami/scripts/pgpool/healthcheck.sh"]
interval: 10s
timeout: 5s
retries: 5
extra_hosts:
- "pg-0:192.168.48.80"
- "pg-1:192.168.48.81"
- "pg-2:192.168.48.82"
# 定义持久卷,只挂载数据和日志目录
volumes:
pgpool_data:
driver: local
driver_opts:
type: none
o: bind
device: /data/pgpool/data/
# pgpool_conf:
# driver: local
# driver_opts:
# type: none
# o: bind
# device: /data/pgpool/conf/
pgpool_logs:
driver: local
driver_opts:
type: none
o: bind
device: /data/pgpool/logs/
4.启动
进入docker-compose.yaml所在目录执行启动命令,先启动主库再启动从库,最后启动pgpool。
docker-compose up -d
检查是否启动成功
docker-compose ps
检查postgresql高可用集群状态
docker exec -it pgpool-0 psql -h 192.168.48.80 -p 9999 -U postgres -c "SHOW pool_nodes;"
输出:
Password for user postgres:
node_id | hostname | port | status | pg_status | lb_weight | role | pg_role | select_cnt | load_balance_node | replication_delay | replication_state | replication_sync_state | last_status_change
---------+---------------+------+--------+-----------+-----------+---------+---------+------------+-------------------+-------------------+-------------------+------------------------+---------------------
0 | 192.168.48.80 | 5432 | up | up | 0.333333 | primary | primary | 2 | false | 0 | | | 2026-06-18 12:19:53
1 | 192.168.48.81 | 5432 | up | up | 0.333333 | standby | standby | 0 | false | 0 | streaming | async | 2026-06-18 12:19:53
2 | 192.168.48.82 | 5432 | up | up | 0.333333 | standby | standby | 0 | true | 0 | streaming | async | 2026-06-18 12:19:53
(3 rows)
各字段详解
|------------------------|---------------------|------------------------------------------------------------|
| 字段 | 值(以 node_id=0 为例) | 含义 |
| node_id | 0, 1, 2 | 后端节点的唯一标识(pgpool 内部编号)。 |
| hostname | 192.168.48.80/81/82 | PostgreSQL 实例的 IP 地址。 |
| port | 5432 | PostgreSQL 的监听端口。 |
| status | up | pgpool 对节点的健康检查结果(up 表示可连接,down 表示不可用)。 |
| pg_status | up | PostgreSQL 实例自身的运行状态(up 表示数据库进程正常)。 |
| lb_weight | 0.333333 | 负载均衡权重,三个节点平均分配(各 1/3),意味着读查询会按此比例分发到三个节点。 |
| role | primary / standby | pgpool 识别的节点角色(主库或从库),用于路由写操作(主)和读操作(从)。 |
| pg_role | primary / standby | PostgreSQL 自身的角色,与 role 一致,确保一致性。 |
| select_cnt | 2 / 0 / 0 | 该节点自 pgpool 启动以来处理的 SELECT 查询次数(由于刚重启不久,主库处理了 2 次,从库还未处理)。 |
| load_balance_node | true(在 node_id=2 上) | 表示本次查询被 pgpool 的负载均衡器路由到了哪个节点(这里是 82)。true 只会出现在其中一个节点上。 |
| replication_delay | 0 | 从库与主库的复制延迟(单位为字节或时间,此处为 0 表示无延迟)。 |
| replication_state | streaming(从库) | 从库正在使用 流复制 同步数据(正常状态)。主库此列为空。 |
| replication_sync_state | async(从库) | 复制模式为 异步复制(PostgreSQL 默认),主库此列为空。 |
| last_status_change | 时间戳 | 该节点最后一次状态变化的时间(从 down 变为 up 或反过来)。 |
关键信息总结
-
主从架构确认
-
主库:
192.168.48.80(负责写入) -
从库:
192.168.48.81和192.168.48.82(负责读取)
-
-
复制链路正常
-
两个从库都通过 流复制 从主库同步数据,延迟为 0,说明数据实时性很好。
-
复制模式是
async(异步),这是 PostgreSQL 的默认配置,适合大多数场景。
-
-
负载均衡生效
-
三个节点的
lb_weight都是 0.333,表示读查询会均匀分发。 -
你的本次查询被路由到了
192.168.48.82(load_balance_node=true),说明 pgpool 的负载均衡算法(如轮询或最少连接)正在工作。
-

5.主从复制验证
这里pgpool是逻辑上的一个数据库,它会连接主库,所以在pgpool上验证主从复制。
连接pgpool的9999端口后,postgres库中插入user表,三个postgresql同时复制user表。
CREATE TABLE "user" (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
password_hash VARCHAR(255) NOT NULL,
first_name VARCHAR(50),
last_name VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
is_active BOOLEAN DEFAULT TRUE
);
查看是否都同步复制了user表
psql -h 192.168.48.80 -p 5432 -U postgres -c "\dt"
psql -h 192.168.48.81 -p 5432 -U postgres -c "\dt"
psql -h 192.168.48.82 -p 5432 -U postgres -c "\dt"
均显示
List of relations
Schema | Name | Type | Owner
--------+------+-------+----------
public | user | table | postgres
(1 row)
示例:
[root@master01 pg-cluster]# docker exec -it pgpool-0 /bin/bash
I have no name!@master01:/$ psql -h 192.168.48.80 -p 5432 -U postgres -c "\dt"
Password for user postgres:
List of relations
Schema | Name | Type | Owner
--------+------+-------+----------
public | user | table | postgres
(1 row)
I have no name!@master01:/$ psql -h 192.168.48.81 -p 5432 -U postgres -c "\dt"
Password for user postgres:
List of relations
Schema | Name | Type | Owner
--------+------+-------+----------
public | user | table | postgres
(1 row)
I have no name!@master01:/$ psql -h 192.168.48.82 -p 5432 -U postgres -c "\dt"
Password for user postgres:
List of relations
Schema | Name | Type | Owner
--------+------+-------+----------
public | user | table | postgres
(1 row)