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

相关推荐
无限进步_13 小时前
【Linux】网络发展背景与协议分层模型
linux·运维·网络
比昨天多敲两行13 小时前
Linux命令行参数,环境变量和程序地址空间
linux·运维·服务器
長安一片月13 小时前
snort安装与使用
linux·运维·服务器
凭X而动13 小时前
postgresql18.1部署
数据库·postgresql
万邦科技Lafite13 小时前
京东商品详情 API 接口全面讲解
java·数据库·redis·api·电商开放平台
无风听海13 小时前
MongoDB GridFS 一些处理细节解析
数据库·mongodb
青云计划13 小时前
Mysql
数据库·mysql
SelectDB13 小时前
Agent 应用范式下,企业数据基础设施如何演进?
大数据·数据库·数据分析
kyle~13 小时前
C++---段错误(SIGSEGV)
linux·运维·c++·机器人
杜子不疼.13 小时前
【C++ AI 大模型接入 SDK】 - 环境搭建
开发语言·数据库·c++