流复制通过主库发送WAL日志、备库接收并应用实现数据同步。需配置主库wal_level、max_wal_senders、pg_hba.conf允许复制连接,使用pg_basebackup创建基础备份,备库启用hot_standby并启动服务;验证通过pg_stat_replication和pg_is_in_recovery()检查状态,注意网络、权限、WAL保留策略及磁盘空间。
在PostgreSQL的世界里,流复制(Streaming Replication)无疑是构建高可用和数据冗余基石的关键技术。简单来说,它就是让你的数据有一个或多个实时备份,以防不测,或者分担读请求的压力。配置和建立流复制数据源,核心就在于主库(Primary)和备库(Standby)之间,通过传输和应用预写日志(WAL)来达到数据同步的目的。
说实话,第一次接触流复制,光是看着那些配置参数就有点头大。但一旦理解了背后的逻辑,其实也就那么回事。核心在于让主库知道它需要发送WAL日志,让备库知道它需要接收并应用这些日志。整个过程可以粗略分成几步,每一步都有其考量。
解决方案
配置和建立PostgreSQL流复制数据源,通常涉及主库的准备、基础备份的创建以及备库的配置启动。
1. 主库(Primary)配置
首先,我们需要调整主库的一些参数,使其能够支持流复制。这主要在
postgresql.conf
和
pg_hba.conf
文件中进行。
-
修改
postgresql.conf
:
-
wal_level = replica
:这是最基础的,它告诉PostgreSQL生成足够的WAL信息以支持流复制。在旧版本中可能是
hot_standby
或
logical
,但
replica
是当前推荐的。
-
max_wal_senders = 10
:这个参数定义了主库最多可以同时支持多少个备库连接来传输WAL。根据你的需求和备库数量设置一个合理的值,比如5-10个通常足够。
-
wal_keep_size = 5GB
:这决定了主库在
pg_wal
目录下保留多少WAL文件,以供备库在需要时拉取。如果备库因为网络或其他原因短暂掉线,这些保留的WAL文件可以帮助它追赶进度。这个值需要根据你的WAL生成速度和备库的掉线容忍度来估算,太大浪费空间,太小容易导致备库无法追赶。
-
listen_addresses = '*'
: 确保主库监听所有网络接口,这样备库才能连接上来。或者指定具体的IP地址。
-
hot_standby = on
: 虽然这个参数主要在备库上起作用,但为了完整性,有时在主库上也会提及,不过它对主库本身的功能影响不大。
# postgresql.conf (Primary) wal_level = replica max_wal_senders = 10 wal_keep_size = 5GB # 或者根据实际情况调整 listen_addresses = '*'
-
-
修改
pg_hba.conf
:
- 添加一行允许备库连接到主库进行复制的规则。这通常是针对
replication
数据库用户。
- 例如,如果你的备库IP是
192.168.1.100
,且你打算使用一个名为
repl_user
的用户进行复制:
# pg_hba.conf (Primary) host replication repl_user 192.168.1.100/32 md5
请确保
repl_user
在主库中已创建,并且拥有
replication
权限。
- 添加一行允许备库连接到主库进行复制的规则。这通常是针对
-
重启主库: 所有配置更改后,需要重启PostgreSQL服务以使之生效。
2. 创建基础备份(Base Backup)
在主库配置完成后,我们需要从主库创建一个完整的数据备份,作为备库的起点。这个过程通常使用
pg_basebackup
工具来完成。
-
在备库机器上执行: 选择一个空目录作为备库的数据目录,然后运行
pg_basebackup
命令。
# 假设备库数据目录是 /var/lib/postgresql/14/main_standby # -h: 主库地址 # -p: 主库端口 # -U: 复制用户 # -D: 备库数据目录 # -Fp: plain格式,非tar # -Xs: streaming模式,复制WAL日志 # -R: 自动生成 recovery.conf (或 standby.signal 和 postgresql.auto.conf) pg_basebackup -h <primary_ip> -p 5432 -U repl_user -D /var/lib/postgresql/14/main_standby -Fp -Xs -R
执行此命令时,会提示输入
repl_user
的密码。成功后,备库数据目录下会包含主库的完整数据,以及一个
standby.signal
文件(PostgreSQL 12及更高版本)或
recovery.conf
文件(旧版本),用于指示备库启动时进入恢复模式。
3. 备库(Standby)配置与启动
-
修改
postgresql.conf
(备库):
-
hot_standby = on
:如果希望备库在复制的同时,也能接受只读查询,这个参数必须打开。
-
primary_conninfo = 'host=<primary_ip> port=5432 user=repl_user password=<password>'
:这个连接字符串告诉备库如何连接到主库。
-
restore_command = 'cp /path/to/archive/%f %p'
:如果你同时启用了WAL归档,并且希望备库在流复制中断时能从归档中恢复,就需要配置这个。但对于纯流复制,通常不是必需的。
# postgresql.conf (Standby) hot_standby = on # primary_conninfo 通常由 pg_basebackup -R 自动生成在 postgresql.auto.conf 中, # 但你也可以手动添加或修改。 # primary_conninfo = 'host=<primary_ip> port=5432 user=repl_user password=<password>'
请注意,
pg_basebackup -R
选项会自动在备库数据目录下的
postgresql.auto.conf
文件中生成
primary_conninfo
,通常无需手动设置。
-
-
启动备库: 启动备库的PostgreSQL服务。它会自动读取
standby.signal
或
recovery.conf
,并尝试连接主库进行WAL日志的同步和应用。
systemctl start postgresql-14 # 或你的PostgreSQL服务名
流复制的核心原理是什么?为什么我们需要它?
这事儿听起来简单,但背后的原理其实挺精妙的。WAL日志,你可以理解为数据库的所有变更记录,它保证了数据的一致性和持久性。PostgreSQL在任何数据写入磁盘之前,都会先将这些变更写入到WAL日志中。流复制,就是把这些日志实时地从主库“快递”到备库,备库再按顺序“播放”这些变更,将其应用到自己的数据文件中。这个过程是物理级别的复制,效率很高。
至于为什么我们需要它,除了显而易见的数据安全,还有几个关键点:
- 高可用性(High Availability):这是最主要的驱动力。如果主库突然挂了,备库可以迅速地被提升为新的主库,大大减少了业务中断的时间。这就像给你的核心业务数据买了一份实时保险。
- 读扩展(Read Scaling):当你的应用读请求远超写请求时,可以将部分只读查询分流到备库上执行,从而减轻主库的压力,提高整体系统的吞吐量。不过,这需要应用程序层面的支持,能区分读写请求。
- 灾难恢复(Disaster Recovery):如果整个数据中心发生灾难,只要你的备库位于不同的地理位置,就能提供快速的恢复能力。
- 数据分析/报告:有时,我们会在备库上运行一些耗时的数据分析或报告生成任务,避免这些任务影响主库的性能。
对我来说,流复制不仅仅是一个技术配置,它更是一种风险管理策略。尤其是在生产环境中,没有流复制的数据库,就像走钢丝没有安全网,心里总是不踏实。
配置流复制时,有哪些常见的“坑”和注意事项?
我个人觉得,流复制最容易出问题的地方往往不是配置本身,而是对细节的忽略和环境的差异。比如网络延迟,有时能把人折腾疯。还有WAL日志的管理,这绝对是个重灾区。
- 网络连接与防火墙:这是最基础也最容易被忽视的问题。主备库之间必须能够互相访问,特别是主库的5432端口。防火墙规则(如
ufw
或
firewalld
)一定要正确配置,允许复制用户从备库IP连接。我遇到过几次,就是因为防火墙没开通,排查了半天才发现。
-
wal_keep_size
的设置
:这个参数非常关键。如果备库因为网络波动、机器重启等原因暂时掉线,它会尝试从主库拉取缺失的WAL文件。如果主库因为wal_keep_size
设置太小,已经清除了备库需要的WAL文件,那么备库就无法追赶,只能重新做一次基础备份。这是一个很常见的“坑”。所以,
wal_keep_size
要结合你的WAL生成速度和备库的掉线容忍度来设置,或者配合WAL归档(
archive_mode
)使用,让备库可以从归档中获取历史WAL。
-
pg_hba.conf
权限问题
:复制用户必须有正确的权限,并且在pg_hba.conf
中有对应的
replication
规则。如果这里配置错了,备库根本连不上主库。
- 用户权限与密码:复制用户(如
repl_user
)必须在主库上创建,并拥有
replication
权限。密码也要确保正确,并且在
primary_conninfo
中配置无误。
- 磁盘空间:备库需要和主库一样甚至更多的磁盘空间来存储数据和WAL日志。如果备库磁盘满了,复制就会停止。
- PostgreSQL版本一致性:强烈建议主备库使用完全相同的PostgreSQL版本,包括小版本号。虽然有时大版本之间在一定条件下也能复制,但为了避免不必要的兼容性问题,最好保持一致。
- 时区与系统时间:主备库的系统时间最好同步,并使用相同的时区设置,这有助于日志分析和事件关联。
- 故障切换(Failover):很多人只关注了如何搭建流复制,却忽略了当主库真正挂掉时,如何安全、有效地将备库提升为主库。这需要一套成熟的故障切换策略和工具(如
pg_auto_failover
,
Patroni
等),以及应用程序如何感知新的主库地址。单纯的手动提升备库为主库,操作不当可能会导致数据丢失或脑裂。
如何验证流复制是否正常工作,以及故障排查的初步思路?
配置完流复制,别以为就万事大吉了。最关键的是要确认它真的在工作,而且是健康地工作。我见过太多次,配置好了,但一检查发现备库早就掉队了,或者干脆就没连上。所以,定期的检查和一套初步的排查思路是必不可少的。
验证流复制状态:
-
在主库上检查
pg_stat_replication
视图: 这是最直接的检查方式。连接到主库,执行:
SELECT client_addr, state, sync_state, sync_priority, replay_lag, write_lag, flush_lag FROM pg_stat_replication;
-
client_addr
:应该显示备库的IP地址。
-
state
:应该是
streaming
,表示正在实时传输WAL。
-
sync_state
:如果是同步复制,会显示
sync
;如果是异步复制,则显示
async
。
-
replay_lag
:这个非常重要,表示备库落后主库多少时间。理想情况下应该非常小,接近0。如果持续增大,说明备库跟不上了。
-
-
在备库上检查
pg_is_in_recovery()
: 连接到备库,执行:
SELECT pg_is_in_recovery();
如果返回
t
(true),说明备库正在恢复模式,即正在进行流复制。如果返回
f
,说明它已经脱离恢复模式,可能已经提升为主库,或者复制失败。
-
检查数据库日志文件: 主备库的PostgreSQL日志文件(通常在数据目录的
log
文件夹下)会记录复制相关的事件和错误信息。查看这些日志是排查问题的第一步。例如,主库日志会记录备库的连接信息,备库日志会记录它尝试连接主库和应用WAL的情况。
-
写入测试数据并验证: 如果备库设置为
hot_standby = on
,你可以在主库上插入一条数据,然后在备库上立即查询,看是否能查到。这是最直观的验证方法。
故障排查的初步思路:
当发现流复制不正常时,可以按照以下步骤进行排查:
-
网络连通性检查: 首先确认主备库之间网络是否畅通。从备库
ping
主库IP,或者用
telnet <primary_ip> 5432
检查端口是否开放。防火墙问题往往在这里暴露。
-
主库
pg_hba.conf
和用户权限: 检查主库的
pg_hba.conf
是否允许备库IP的
replication
用户连接。同时确认
repl_user
是否存在且密码正确。
-
主库
postgresql.conf
参数: 确认
wal_level = replica
和
max_wal_senders
是否配置正确,并且主库已重启生效。
-
备库日志文件: 仔细查看备库的PostgreSQL日志。它通常会告诉你为什么连接不上主库,或者为什么无法应用WAL。常见的错误信息包括“could not connect to server”、“FATAL: password authentication failed”、“WAL segment xxx not found”等。
-
wal_keep_size
或 WAL归档问题: 如果备库日志显示“WAL segment xxx not found”,这通常意味着备库落后太多,主库已经清理了它需要的WAL文件。这时候你可能需要:
- 增大主库的
wal_keep_size
。
- 如果启用了WAL归档,检查归档是否正常工作,以及备库的
restore_command
是否正确。
- 最坏的情况,可能需要重新做一次基础备份。
- 增大主库的
-
备库磁盘空间: 检查备库的数据目录所在分区是否有足够的空间。磁盘满会导致WAL无法写入,复制中断。
-
primary_conninfo
检查: 确认备库的
postgresql.auto.conf
或
postgresql.conf
中的
primary_conninfo
连接字符串是否正确,包括主库IP、端口、用户和密码。
排查问题就像侦探破案,需要耐心和细致。从最基础的网络和权限开始,逐步深入到配置参数和日志分析,通常都能找到症结所在。
word 防火墙 工具 ai 地理位置 数据丢失 为什么 auto 字符串 接口 signal 事件 异步 postgresql 数据库 数据分析 数据中心