PostgreSQL通过pg_basebackup物理备份搭建流复制备库(Streaming Replication Standby)

PostgreSQL 流复制(Streaming Replication)是实现高可用性、负载均衡和灾难恢复的核心技术。它允许一个主服务器(Primary/Master)将一个或多个备用服务器(Standby/Replica)保持为实时更新状态。

以下为从零开始用pg_basebackup物理备份搭建 PostgreSQL 流复制(异步/同步)的详细步骤。


架构概述

  • 主服务器 (Primary):接受读写操作的数据库服务器。
  • 备服务器 (Standby):接收并应用主服务器的 WAL (Write-Ahead Logging) 数据,通常只读。
  • 流复制:备服务器通过一个普通的 PostgreSQL 连接,实时地、流式地从主服务器接收 WAL 记录,并在备服务器上重放。
  • 同步与异步 :
    • 异步(默认):主服务器提交事务后,无需等待备服务器确认即向客户端返回成功。性能好,但有少量数据丢失风险。
    • 同步:主服务器提交事务后,必须等待至少一个备服务器确认收到WAL数据后才向客户端返回成功。数据安全性高,但会增加事务延迟。

本指南以异步流复制为例。


详细步骤

假设我们有两台服务器:

  • 主服务器 : 192.168.1.10, 端口 5432
  • 备服务器 : 192.168.1.11, 端口 5432
第一部分:主服务器配置
  1. 创建复制专用用户

    在主服务器上,创建一个专门用于流复制的用户。这个用户需要有 REPLICATION 权限。

    sql 复制代码
    psql -U postgres -d postgres
    sql 复制代码
    CREATE ROLE rep WITH LOGIN REPLICATION PASSWORD 'rep123';
  2. 配置 pg_hba.conf

    修改 PostgreSQL 的主机基于认证配置文件 (pg_hba.conf),允许备服务器以 repl_user 用户连接进行复制。

    bash 复制代码
    # 找到你的 pg_hba.conf 位置
    # 通常位于 $PGDATA/pg_hba.conf 或 /etc/postgresql/版本/主目录/pg_hba.conf
    sudo vi $PGDATA/pg_hba.conf

    在文件末尾添加一行:

    复制代码
    # TYPE  DATABASE        USER        ADDRESS                 METHOD
    host    replication     repl_user   192.168.1.11/32        md5
    • replication: 特殊的伪数据库名,表示此规则用于流复制连接。
    • repl_user: 我们刚刚创建的复制用户。
    • 192.168.1.11/32: 备服务器的 IP 地址, /32 表示一个主机。
    • md5: 要求密码认证。
  3. 配置 postgresql.conf

    修改 PostgreSQL 的主配置文件 (postgresql.conf)。

    bash 复制代码
    sudo vi $PGDATA/postgresql.conf

    修改或确保以下参数已设置:

    properties 复制代码
    # 监听所有连接
    listen_addresses = '*'
    # 服务端口
    port = 5432
    # 开启 WAL 归档(虽然不是流复制必需,但强烈建议)
    archive_mode = on
    archive_command = 'test ! -f /path/to/archive/%f && cp %p /path/to/archive/%f'
    # 设置 Wal Level 为 replica 或更高级别,这是流复制的必要条件
    wal_level = replica
    # 设置最大 WAL 发送进程数,至少大于等于备服务器数量
    max_wal_senders = 10
    # 设置保留在 pg_wal 目录中的 WAL 段文件的最小数量,防止主服务器在备服务器追上之前删除需要的 WAL
    wal_keep_size = 1GB
    # 在同步复制中设置备服务器名称,异步复制可先忽略
    # synchronous_standby_names = 'FIRST 1 (standby1)'
  4. 重启主服务器

    使配置生效。

    bash 复制代码
    sudo systemctl restart postgresql 
    或
    pg_ctl -D $PGDATA restart

第二部分:备服务器配置
  1. 停止 PostgreSQL 服务

    bash 复制代码
    sudo systemctl stop postgresql
    或
    pg_ctl -D $PGDATA stop
  2. 清空数据目录

    确保备服务器的 PostgreSQL 数据目录(例如 /var/lib/postgresql/版本/main)是空的。(操作前请务必备份原有数据!)

    bash 复制代码
    sudo su - postgres
    cd $PGDATA
    rm -rf *
  3. 使用 pg_basebackup 进行基础备份

    这是最关键的一步。它从主服务器获取一个完整的数据快照,并自动配置 standby.signal 文件。

    bash 复制代码
    # 以 postgres 用户执行
    pg_basebackup -h 192.168.1.10 -D $PGDATA -U repl_user -P -v -R -W
    • -h 192.168.1.10: 主服务器的 IP 地址。
    • -D $PGDATA: 指定备服务器的数据目录,将备份文件存储于此。
    • -U repl_user: 使用之前创建的复制用户。
    • -P: 显示进度。
    • -v: 详细模式。
    • -R: (重要) 自动创建 standby.signal 文件并在 postgresql.auto.conf 中写入连接信息。这大大简化了配置。
    • -W: 在执行前提示输入密码(repl_user 的密码)。

    执行成功后,你会在备服务器的 $PGDATA 目录下发现一个 standby.signal 文件,并且 postgresql.auto.conf 文件中包含了主服务器的连接信息。

  4. (可选)手动配置备服务器(如果未使用 -R 参数)

    如果你没有使用 -R 参数,需要手动执行以下步骤:

    a. 创建 standby.signal 文件:

    bash 复制代码
    touch $PGDATA/standby.signal

    b. 在 postgresql.auto.conf 或 postgresql.conf 中添加:

    properties 复制代码
    primary_conninfo = 'host=192.168.1.10 port=5432 user=repl_user password=rep123'

    注意 :在生产环境中,建议将密码存储在 ~/.pgpass 文件中,而不是直接写在配置文件中。

    【~/.pgpass配置方法见博客:https://blog.csdn.net/liumangtuzi888/article/details/152603650?spm=1011.2124.3001.6209】


第三部分:启动与验证
  1. 启动备服务器

    bash 复制代码
    sudo systemctl start postgresql
    或
    pg_ctl -D $PGDATA start
  2. 检查备服务器日志

    启动后,立即检查备服务器的日志文件,查看是否有错误。

    bash 复制代码
    tail -f $PGDATA/log/postgresql-Mon.log

    你应该能看到类似以下的信息,表明流复制已经开始:

    复制代码
    LOG:  database system is ready to accept read-only connections
    LOG:  started streaming WAL from primary at 0/3000000 on timeline 1
  3. 在主服务器上验证复制状态

    连接到主服务器,查询复制状态。

    sql 复制代码
    psql -U postgres -d postgres
    sql 复制代码
    -- 查看发送进程状态
    SELECT application_name, client_addr, state, sync_state, sync_priority
    FROM pg_stat_replication;

    预期结果 :你应该能看到一行记录,其中 application_name 通常是 walreceiver,client_addr 是备服务器的 IP (192.168.1.11),state 为 streaming,sync_state 为 async(对于异步复制)。这表明流复制正在正常运行。

  4. 在备服务器上测试

在备库上查询主从流复制状态:

psql -p 5432 -c "SELECT pg_is_in_recovery();"

-- 结果应为 t (true)

psql -p 5432 -c "SELECT * FROM pg_stat_wal_receiver;"

连接到备服务器,尝试执行写操作,应该会被拒绝。

复制代码
```sql
psql -U postgres -d postgres
```

```sql
-- 这应该成功,因为备服务器是只读的
SELECT count(*) FROM your_table_name;

-- 这应该失败,并提示数据库是只读的
INSERT INTO your_table_name VALUES (...);
```

故障排查

  • 连接失败 :检查主备服务器之间的网络、防火墙设置,以及 pg_hba.conf 中的配置。
  • 认证失败 :确认 repl_user 的密码是否正确,以及 pg_hba.conf 中的 md5 方法。
  • WAL 相关错误 :检查主服务器上的 wal_level、max_wal_senders 和 wal_keep_size 设置是否足够。
  • 始终查看日志:主备服务器的日志是解决问题的第一手资料。

升级到同步复制

如果你想配置同步复制,只需修改主服务器 的 postgresql.conf:

properties 复制代码
synchronous_standby_names = 'FIRST 1 (standby1)'

并在备服务器的 primary_conninfo 中设置一个 application_name(如果使用 -R 参数,它可能已经自动设置了,检查 postgresql.auto.conf)。

properties 复制代码
primary_conninfo = 'host=192.168.1.10 port=5432 user=repl_user password=YourSecurePassword123 application_name=standby1'

然后重新加载主、备服务器配置:pg_ctl reload。

完成以上步骤,分别成功搭建了一个 PostgreSQL 异步和同步流复制环境。

相关推荐
阳光九叶草LXGZXJ7 小时前
达梦数据库-报错-15-列【XXX】长度超出定义
linux·运维·数据库·sql·学习
字节渡客7 小时前
Redis键明明过期了,业务还在读到旧数据
数据库·redis·spring
黄大刀8 小时前
DataPulse一款开箱即用的SCADA(四)-历史记录
运维·scada·动环
正在走向自律9 小时前
AI数据分析与可视化:从基础到应用实践
服务器·人工智能·python·机器学习·数据分析·pandas
OnlineProxy9 小时前
亚马逊多账号运营:如何在规避“关联封号”风险的同时实现电商规模化扩张
服务器·数据库·redis
归秋14210 小时前
2026 企业 AI 办公工具选型指南:从评估框架到产品适配
大数据·运维·人工智能
Android系统攻城狮10 小时前
Linux Gstreamer深度解析之gst_audio_encoder_set_frame_max调用流程与实战(六十一)
android·linux·运维·音视频·gstreamer音视频·音视频进阶·gstreamer音视频进阶
91刘仁德11 小时前
IP协议详解:从IP协议头到网段划分、路由与NAT
linux·服务器·网络·网络协议·tcp/ip
辻弋20111 小时前
五年前的旅行视频糊成马赛克?Video2X用Real-ESRGAN逐帧重建细节,但只支持Windows、集显用户建议直接放弃
服务器·数据库·windows·游戏引擎·电脑
硅基手札12 小时前
【Linux内核专栏 14】网络协议栈
linux·运维·网络协议