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.confpostgresql.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 通常是 walreceiverclient_addr 是备服务器的 IP (192.168.1.11),statestreamingsync_stateasync(对于异步复制)。这表明流复制正在正常运行。

  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_levelmax_wal_senderswal_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 异步和同步流复制环境。

相关推荐
小蒜学长3 小时前
springboot基于javaweb的小零食销售系统的设计与实现(代码+数据库+LW)
java·开发语言·数据库·spring boot·后端
云边有个稻草人3 小时前
从内核调优到集群部署:基于Linux环境下KingbaseES数据库安装指南
linux·数据库·金仓数据库管理系统
EnCi Zheng3 小时前
JPA 连接 PostgreSQL 数据库完全指南
java·数据库·spring boot·后端·postgresql
Raymond运维3 小时前
MySQL包安装 -- RHEL系列(Yum资源库安装MySQL)
linux·数据库·mysql
夜月yeyue3 小时前
ART 加速器、流水线与指令预测的关系详解
linux·服务器·c语言·单片机·嵌入式硬件·性能优化·嵌入式高阶技巧
迎風吹頭髮4 小时前
UNIX下C语言编程与实践36-UNIX 时钟:系统时间、高分辨率时间与日历时间的转换与使用
服务器·c语言·unix
旗讯数字4 小时前
企业OCR实战:基于OCR技术实现双节差旅报销单表格解析与文字信息自动化采集
运维·自动化·ocr·表格识别
bst@微胖子4 小时前
Harmony中EventHub实现发布订阅
linux·运维·ubuntu
为java加瓦4 小时前
IO多路复用的两种触发机制:ET和LT触发机制。以及IO操作是异步的还是同步的理解
java·服务器·网络