现在很多企业应用都特别依赖数据库能不能一直正常跑,而 PostgreSQL 是一个功能强大又免费的关系型数据库,它自带的流复制(Streaming Replication)功能可以让我们轻松搭起一套主从结构,这篇文章会手把手教你从零开始配置,并告诉你主库挂了怎么切到备库,以及怎么检查两边数据是不是同步得及时。


一、流复制基本原理

PostgreSQL 的流复制是靠 WAL(也就是预写日志)来实现的,主库每做一次写操作就会生成对应的日志,然后实时把这些日志发给备库,备库收到后就按顺序重新执行一遍,这样两边的数据就能保持一致,这种做法不仅能起到备份作用,还能把读请求分给备库处理,从而减轻主库的压力。

说明:本文用的是 PostgreSQL 14 或更新的版本,适合常见的 Linux 系统,比如 CentOS、Ubuntu 这些。


二、实验环境准备

  • 主库 IP:192.168.1.10
  • 备库 IP:192.168.1.11
  • 两边装的 PostgreSQL 版本要完全一样(建议至少用 14 或更高)
  • 两台机器之间网络要通,防火墙不能拦住 5432 端口

三、主库端配置步骤

1. 先建一个专门用来做数据同步的账号

CREATE ROLE repl_user WITH REPLICATION LOGIN PASSWORD 'your_secure_password';

2. 打开 postgresql.conf 文件(一般在 /var/lib/pgsql/14/data/postgresql.conf/etc/postgresql/14/main/postgresql.conf),把下面几个参数改一下:

wal_level = replica
max_wal_senders = 10
hot_standby = on
listen_addresses = '*'

3. 再去 pg_hba.conf 里加一行规则,允许备库连过来拉日志

# TYPE  DATABASE        USER            ADDRESS                 METHOD
host    replication     repl_user       192.168.1.11/32         md5

4. 改完之后重启一下 PostgreSQL 服务让设置生效

sudo systemctl restart postgresql-14

四、备库端初始化配置

1. 先停掉备库的服务,然后清空原来的数据目录

sudo systemctl stop postgresql-14
sudo rm -rf /var/lib/pgsql/14/data/*

2. 接着用 pg_basebackup 命令从主库把整个数据拷过来

sudo -u postgres pg_basebackup \
  -h 192.168.1.10 \
  -U repl_user \
  -D /var/lib/pgsql/14/data \
  -P -v -R -X stream

这里 -R 会自动创建 standby.signal 文件,并把主库地址写进 postgresql.auto.conf,而 -X stream 表示直接用流的方式传日志,不用临时存文件。

3. 最后启动备库服务

sudo systemctl start postgresql-14

这时候备库会以只读模式启动,并开始接收主库发来的日志进行同步。


五、检查复制是不是在正常工作

在主库上查一下有没有备库连上来:

SELECT * FROM pg_stat_replication;

如果看到一条记录,而且 state 字段是 streaming,那就说明连接没问题。

在备库上确认自己是不是处于备用状态:

SELECT pg_is_in_recovery();  -- 返回 true 就表示当前是备机

六、主库出问题了怎么办?手动把备库变成主库

万一主库宕机了,你可以手动把备库提升成新的主库:

方法一:直接用 pg_ctl promote 命令

sudo -u postgres pg_ctl promote -D /var/lib/pgsql/14/data

方法二:创建一个触发文件(前提是你提前在配置里指定了 promote_trigger_file

touch /tmp/promote.trigger

注意:一旦完成提升,原来的主库就不能自动变回备库了,需要你重新配置它去连新的主库。


七、怎么知道两边数据同步有没有慢下来

1. 可以对比两边的 WAL 位置(单位是字节)

-- 在主库运行
SELECT pg_current_wal_lsn();

-- 在备库运行
SELECT pg_last_wal_replay_lsn();

两个值相减,就是还没同步过去的日志量。

2. 更直观的是看时间差

-- 在备库运行
SELECT 
  now() - pg_last_xact_replay_timestamp() AS replication_delay;

如果结果是 00:00:00,说明完全跟上了;如果是 00:01:20,就代表慢了 1 分 20 秒。

3. 还可以查 WAL 接收器的状态

SELECT * FROM pg_stat_wal_receiver;

这个视图会显示最后收到日志的时间、连接是否正常等信息,方便排查问题。


八、容易碰到的问题和实用建议

  • 网络偶尔断一下:备库通常能自己重连,只要主库还没删掉那些还没同步完的日志文件,就能继续接着同步。
  • 延迟特别大:可能是网络带宽不够、磁盘写入太慢,或者主库负载太高。
  • 上线前的小建议
    • 如果业务要求数据绝对不能丢,可以把 synchronous_commit 设成 remote_apply,不过这样写入速度会变慢
    • 推荐搭配 Patroni 加 etcd 这类工具,能自动检测故障并完成切换
    • 给复制延迟设个告警阈值,比如超过 10 秒就发通知,这样能早点发现问题

结语

利用 PostgreSQL 自带的流复制功能,我们能很快搭出一套防止单点失效的主从系统,再配合本文提到的切换方法和监控手段,遇到故障时就能快速恢复服务,保证业务不中断。

再提醒一句:主从复制只是高可用的基础,真正在生产环境用的时候,最好加上 Patroni 或 repmgr 这样的管理工具,让整个流程更自动化、更省心。

欢迎大家在评论区留言,分享你的实际经验或者遇到的难题!

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐