腾讯云Linux云服务器搭建PostgreSQL主从架构完全指南
为什么需要PostgreSQL主从架构
数据库是绝大多数业务系统的核心资产。单机部署的PostgreSQL一旦遭遇硬件故障、操作系统崩溃或网络中断,整个业务就会陷入停摆。一次宕机往往意味着数小时的业务损失,数据恢复还需要额外的人工介入时间。主从复制架构通过将数据实时同步到备用节点,让系统在故障发生时能够快速切换到健康的副本,将业务中断时间从小时级压缩到分钟级。
在腾讯云环境中,你可以选择云数据库PostgreSQL产品(默认支持双机高可用一主一从架构),也可以在两台或多台云服务器CVM上自行搭建PostgreSQL主从环境。后者赋予你更高的自主控制权,也更能理解主从复制的底层运作机制。本文聚焦后者——在腾讯云Linux云服务器上,从零开始搭建一套生产级的PostgreSQL主从流复制架构。
需要先登录腾讯云控制台,点击:腾讯云控制台,还没有账号,点击:注册后再关联,已有账号点击:登录后再关联
主从复制的技术原理
PostgreSQL的主从复制基于预写日志机制。主数据库在写入数据之前,会先将变更记录写入WAL日志。流复制技术则更进一步——主服务器在WAL记录产生时立即以TCP流的形式传送给备服务器,而不必等待WAL文件完成归档。
流复制属于物理复制,从实例级复制出一个与主库完全一致的副本。这种复制方式支持同步与异步两种模式。异步复制下,主库执行完写操作后立即向应用返回响应,然后再向从库复制数据;同步复制则要求主库等待至少一个从库确认接收并应用了变更后才返回。两种模式在性能与数据一致性之间提供了不同的权衡选择。
PostgreSQL 9.x版本之后引入的流复制机制,让备服务器通过TCP流持续从主服务器接收数据。备库启动后,其wal_receiver进程向主库发送连接请求,主库收到后启动wal_sender进程与之建立连接。数据就在这一送一收之间完成了实时同步。
环境准备与基础配置
服务器规格要求
在腾讯云CVM上搭建主从架构,需要准备两台Linux云服务器。一台作为主库,一台作为从库。两台服务器需满足以下基本要求:
- 操作系统:CentOS 7/8/9或Ubuntu 20.04+
- PostgreSQL版本:主从库必须完全一致
- 网络:两台服务器网络互通,防火墙放行5432端口
- 磁盘:从库磁盘空间不小于主库
- 时间同步:建议配置NTP确保两台服务器时间一致
本文示例使用以下环境:主库IP为192.168.50.120,从库IP为192.168.50.125,PostgreSQL版本为14。实际操作中请替换为你的腾讯云CVM真实内网IP。
安装PostgreSQL
在主库和从库上分别安装PostgreSQL。不同操作系统的安装命令略有差异。
CentOS/RHEL系统:
# 添加官方仓库
sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm
# 安装PostgreSQL 14
sudo dnf install -y postgresql14-server postgresql14-contrib
# 初始化数据库
sudo /usr/pgsql-14/bin/postgresql-14-setup initdb
# 启动服务并设置开机自启
sudo systemctl enable --now postgresql-14Ubuntu/Debian系统:
# 导入GPG密钥
wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add -
# 添加APT仓库
echo "deb http://apt.postgresql.org/pub/apt/ $(lsb_release -cs)-pgdg main" | sudo tee /etc/apt/sources.list.d/pgdg.list
# 更新并安装
sudo apt update
sudo apt install -y postgresql-14 postgresql-contrib-14安装完成后,PostgreSQL数据目录默认在/var/lib/pgsql/14/data/(CentOS)或/var/lib/postgresql/14/main/(Ubuntu)。
主库配置
创建复制专用用户
主库需要创建一个专门用于复制的数据库用户,从库将使用这个用户连接主库拉取数据。
# 切换到postgres用户
sudo -u postgres psql
# 创建复制用户
CREATE USER replica WITH REPLICATION ENCRYPTED PASSWORD 'your_secure_password';
# 退出psql
\q修改postgresql.conf
编辑主库的postgresql.conf配置文件,启用流复制相关参数。
# 监听所有网络接口
listen_addresses = '*'
# 设置WAL日志级别为replica,启用流复制
wal_level = replica
# 最大WAL发送进程数,建议大于从库数量
max_wal_senders = 10
# 从库向主库报告状态的最大间隔时间
wal_receiver_status_interval = 10s
# 开启日志收集
logging_collector = on
log_directory = 'pg_log'
# 同步复制相关参数(后续详解)
# synchronous_commit = on
# synchronous_standby_names = '*'配置文件位置:CentOS下为/var/lib/pgsql/14/data/postgresql.conf,Ubuntu下为/etc/postgresql/14/main/postgresql.conf。
修改pg_hba.conf
编辑pg_hba.conf,添加从库IP的访问权限,允许复制用户连接。
# 允许从库IP使用复制用户连接
host replication replica 192.168.50.125/32 md5
# 允许从库IP连接任意数据库(可选)
host all all 192.168.50.125/32 md5重启主库服务
# CentOS
sudo systemctl restart postgresql-14
# Ubuntu
sudo systemctl restart postgresql从库搭建
停止从库服务并清空数据目录
从库的数据目录需要先清空,因为接下来要从主库拉取完整的数据副本。
# CentOS
sudo systemctl stop postgresql-14
sudo rm -rf /var/lib/pgsql/14/data/*
# Ubuntu
sudo systemctl stop postgresql
sudo rm -rf /var/lib/postgresql/14/main/*使用pg_basebackup拉取主库数据
pg_basebackup是PostgreSQL自带的物理备份工具,13及以上版本均支持。该工具会从主库复制完整的数据文件到从库。
# 以postgres用户执行
sudo -u postgres pg_basebackup -h 192.168.50.120 -U replica -D /var/lib/pgsql/14/data/ -P -v -R -X stream
# 参数说明:
# -h:主库IP地址
# -U:复制用户名
# -D:从库数据目录
# -P:显示进度
# -v:详细输出
# -R:自动生成standby.signal和postgresql.auto.conf
# -X stream:使用流式方式传输WAL日志-R参数会自动在从库数据目录中创建两个关键文件:
standby.signal:标识该实例为从库,PostgreSQL启动时会进入备机恢复模式postgresql.auto.conf:记录主库连接信息,包含primary_conninfo参数
如果手动创建,standby.signal文件内容为空即可。
配置从库的postgresql.conf
从库的配置文件从主库同步过来后,需要做针对性调整。
# 从库配置关键参数
hot_standby = on # 允许从库提供只读查询
# wal_level不再需要,从库不产生WAL
# max_wal_senders从库不需要启动从库服务
# CentOS
sudo systemctl start postgresql-14
# Ubuntu
sudo systemctl start postgresql启动后,从库会自动根据postgresql.auto.conf中的primary_conninfo连接到主库,开始接收并应用WAL数据。
验证主从复制状态
在主库上执行以下SQL,查看当前的复制连接信息:
SELECT * FROM pg_stat_replication;该视图返回的关键字段包括:
pid:wal_sender进程IDapplication_name:从库标识state:复制状态(streaming表示正常流式复制)sync_state:同步模式(async/sync/potential)write_lag:写入延迟flush_lag:刷盘延迟replay_lag:回放延迟
在从库上执行以下SQL,确认是否处于恢复模式:
SELECT pg_is_in_recovery();返回true表示从库正常运行在备机模式。若返回false,说明从库被提升为主库或配置有误。
查看从库接收WAL的进度:
SELECT * FROM pg_stat_wal_receiver;同步复制与异步复制
PostgreSQL流复制支持两种同步模式。
异步复制
异步复制是默认模式。主库执行完事务后立即返回成功,不等待从库确认。这种模式性能最高,但主库故障时可能丢失尚未同步到从库的数据。
同步复制
同步复制要求主库等待至少一个同步从库确认WAL写入(或回放)后才返回成功。通过配置synchronous_commit参数可以精细控制同步级别:
on:等待从库将WAL写入磁盘remote_write:等待从库收到WAL并写入操作系统缓存remote_apply:等待从库完成WAL回放,事务在从库上可见
启用同步复制需要在主库配置:
synchronous_commit = on
synchronous_standby_names = '*'synchronous_standby_names可以指定具体的从库名称,也可以使用*匹配所有同步从库。
同步复制保证了数据的强一致性,但会带来性能开销——如果从库故障或网络延迟,主库的写操作会被阻塞。生产环境中通常根据业务对数据丢失的容忍度来选择同步模式。
监控与告警
复制延迟监控
复制延迟是主从架构中最需要关注的指标。腾讯云数据库PostgreSQL产品提供详细的监控指标,自建环境则可以通过以下方式监控:
在主库查询复制延迟:
SELECT
application_name,
client_addr,
state,
sync_state,
EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp())) AS replay_lag_seconds
FROM pg_stat_replication;pg_last_xact_replay_timestamp()返回从库最后回放事务的时间戳,与当前时间的差值即为回放延迟。
常用监控SQL
-- 查看所有复制连接
SELECT pid, application_name, client_addr, state, sync_state FROM pg_stat_replication;
-- 查看WAL发送进度
SELECT pg_current_wal_lsn(), pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) AS lag_bytes
FROM pg_stat_replication;
-- 检查从库是否在线
SELECT EXISTS(SELECT 1 FROM pg_stat_replication WHERE state = 'streaming');在腾讯云环境中,可以结合云监控服务配置告警策略,当复制延迟超过阈值时触发通知。
手动故障切换
PostgreSQL自身不提供自动故障切换功能,但支持手动将从库提升为主库。
提升从库为主库
在从库上执行以下命令,将其从恢复模式提升为可读写的主库:
sudo -u postgres pg_ctl promote -D /var/lib/pgsql/14/data/或者使用SQL命令(需超级用户权限):
SELECT pg_promote();提升操作会删除standby.signal文件,从库变为独立主库。此操作不可逆——被提升的从库无法通过简单操作恢复为从库状态。
将原主库降级为从库
原主库恢复后,如需将其重新加入集群作为新的从库,需要重新执行从库搭建流程:
- 清空原主库的数据目录
- 使用
pg_basebackup从新主库拉取数据 - 配置
standby.signal和postgresql.auto.conf - 启动服务
如果原主库的数据目录尚有未同步的数据,建议先备份再操作。
自动化高可用:Patroni方案
手动切换虽然可行,但在生产环境中,我们更希望故障发生时系统能自动完成主从切换。Patroni是目前PostgreSQL生态中最流行的自动化高可用工具。
Patroni的核心能力
Patroni使用Python开发,能够管理PostgreSQL集群的故障转移、复制和配置。它通过与分布式配置存储(etcd、ZooKeeper、Consul或Kubernetes)集成,维护集群状态并进行领导者选举。
在腾讯云CVM上部署Patroni
第一步:安装依赖
# 安装Python及pip
sudo yum install -y python3 python3-pip
# 安装Patroni及依赖
sudo CFLAGS="-std=c99" pip3 install patroni psycopg2-binary kazoo
# CentOS 7还需安装编译依赖
yum -y install gcc python3-devel postgresql-devel第二步:配置PostgreSQL超级用户密码
sudo -u postgres psql -c "ALTER ROLE postgres WITH PASSWORD 'your_super_password';"第三步:创建Patroni配置文件
在主库节点创建/etc/patroni/postgres.yml:
scope: pg_cluster
namespace: /postgresql/
name: pg-master
restapi:
listen: 0.0.0.0:8008
connect_address: 192.168.50.120:8008
etcd:
hosts: 192.168.50.120:2379,192.168.50.125:2379
bootstrap:
dcs:
ttl: 30
loop_wait: 10
retry_timeout: 10
maximum_lag_on_failover: 1048576
postgresql:
use_pg_rewind: true
parameters:
wal_level: replica
hot_standby: on
max_wal_senders: 10
max_replication_slots: 10
wal_log_hints: on
postgresql:
listen: 0.0.0.0:5432
connect_address: 192.168.50.120:5432
data_dir: /var/lib/pgsql/14/data
bin_dir: /usr/pgsql-14/bin
authentication:
replication:
username: replica
password: your_replica_password
superuser:
username: postgres
password: your_super_password从库节点的配置文件大同小异,只需修改name和connect_address中的IP地址即可。
第四步:启动Patroni
patroni /etc/patroni/postgres.yml &Patroni启动后会自动初始化PostgreSQL(如果是集群第一个节点)或从主库同步数据(如果是后续节点)。当主库故障时,Patroni会自动选举一个新的主库并完成切换。
性能优化与最佳实践
网络优化
在腾讯云环境中,主从库建议部署在同一个VPC(私有网络)下,使用内网IP进行通信。内网流量不收取费用,且延迟远低于公网。如果必须跨地域部署,需要考虑网络延迟对复制性能的影响。
WAL归档配置
除了流复制,建议同时配置WAL归档,将WAL日志备份到腾讯云COS对象存储或其他远程位置。这样即使主从同时故障,也能通过归档日志恢复数据。
archive_mode = on
archive_command = 'test ! -f /archive/%f && cp %p /archive/%f'从库查询负载
从库启用hot_standby = on后可以承担只读查询,实现读写分离。但需注意:
- 从库的
max_connections应单独设置,不宜过小 - 长时间运行的大查询可能导致从库复制延迟增加
- 可配置
hot_standby_feedback = on防止查询冲突
定期健康检查
建议将以下检查纳入自动化巡检脚本:
- 主从复制状态是否为
streaming - 复制延迟是否在可接受范围内
- 从库磁盘空间是否充足
- WAL日志堆积量是否正常
常见问题与排查思路
复制中断
如果pg_stat_replication中看不到从库连接,检查:
- 主库防火墙是否放行5432端口
pg_hba.conf是否正确配置了从库IP和复制用户- 从库的
primary_conninfo中连接信息是否正确 - 网络是否互通(可用
telnet测试)
复制延迟持续增大
可能原因及对策:
- 从库硬件性能不足——升级从库规格
- 从库执行了长时间查询——优化查询或调整
hot_standby_feedback - 网络带宽不足——检查腾讯云CVM的网络配置
- 主库写入压力过大——考虑使用同步复制或增加从库数量
从库无法启动
检查standby.signal文件是否存在,以及postgresql.auto.conf中的主库连接信息是否正确。如果数据目录损坏,可能需要重新执行pg_basebackup。
总结
在腾讯云Linux云服务器上搭建PostgreSQL主从架构,本质上是在两台CVM之间建立一套基于WAL流复制的数据同步体系。核心步骤包括:主库开启流复制参数并创建复制用户、从库通过pg_basebackup拉取全量数据并配置为备机模式、监控复制状态确保同步正常、根据业务需求选择同步或异步复制模式。
对于生产环境,建议将Patroni等自动化高可用工具纳入架构设计,让故障切换从人工操作走向自动决策。同时结合腾讯云VPC内网低延迟的优势,以及云监控的告警能力,构建一套既可靠又可控的PostgreSQL高可用体系。从单点故障的焦虑中走出来,让数据多一份副本,让服务少一分风险。
常见问题问答
问1:主从库的PostgreSQL版本必须完全一致吗?
是的,流复制属于物理复制,要求主从库的PostgreSQL大版本完全一致。版本不一致可能导致复制失败或数据损坏。建议在搭建前通过postgres --version确认两台服务器的版本号。
问2:同步复制和异步复制该如何选择?
如果业务对数据零丢失有严格要求(如金融交易),选择同步复制;如果可以容忍少量数据丢失(如日志系统、分析类应用),异步复制性能更优。同步复制会带来额外的延迟开销,且从库故障时会阻塞主库写入,需要权衡利弊。
问3:从库搭建时必须清空数据目录吗?
是的。pg_basebackup会将主库的完整数据复制到从库数据目录,要求目标目录为空。如果目录中已有数据,备份过程会失败。建议在拉取数据前先备份原有数据。
问4:如何快速判断主从复制是否正常?
在主库执行SELECT * FROM pg_stat_replication;,如果返回结果中state列为streaming,说明复制正常。在从库执行SELECT pg_is_in_recovery();,返回true表示从库处于备机模式。
问5:主库故障后,如何将业务切换到从库?
在从库执行pg_ctl promote将其提升为新主库,然后修改应用程序的数据库连接地址指向新主库。原主库恢复后,需作为新从库重新接入集群。生产环境建议使用Patroni等工具实现自动切换。
问6:从库可以同时提供读服务吗?
可以。在从库的postgresql.conf中设置hot_standby = on,从库即可接受只读查询。这是实现读写分离的基础配置。但需注意从库的max_connections应单独设置,避免连接数不足。




