PostgreSQL 流复制
1 简介
流复制是指通过 主节点(Primary) 持续发送 WAL 记录,备节点(Standby) 持续接收 WAL 记录并 回放(replay) 的方式来达到实时备份主节点的一种机制。
流复制中最主要的几个进程及其作用如下:
- postgres: 主节点上的后端进程,负责处理客户端连接,一个后端进程对应一个客户端。
- walsender: 主节点上负责发送 WAL 记录的进程。
- walreceiver: 备节点上负责接收 WAL 记录的进程,一个 walreceiver 对应主节点上一个 walsender。
- startup: 备节点上负责启动 walreceiver 和
回放WAL 记录的进程。
PostgreSQL 流复制支持 一主多备,但为了便于理解,后续的内容我们均以 一主一备 为例。
2 启动过程
下图展示了主备之间的启动过程,也就是从请求连接到进入稳定的流复制阶段:
主节点和备节点分别启动。
备节点
startup进程启动。备节点
walreceiver进程启动。备节点
walreceiver进程向主节点发送连接请求,如果主节点未运行,备节点会周期性的重试。主节点收到连接请求后启动一个
walsender来处理连接。备节点发送自己数据库的
最新 LSN(latest LSN)给主节点,该阶段在通信领域也叫做握手(handshaking)。如果备节点的最新 LSN 小于主节点的最新 LSN,那么主节点会把备节点上没有的这些 WAL 记录发送给备节点,备节点接收 WAL 记录并回放,直到和主节点一致,该阶段也叫做
追赶(catch-up)。主备节点数据达到一致后则进入稳定的
流复制(streaming)阶段。
3 复制过程
下图展示了在进入稳定流复制阶段之后,主备节点之间的通信过程:
主节点
postgres进程提交事务并刷盘了一些 WAL 记录到段文件。主节点
walsender进程马上把新写入的 WAL 记录发送给备节点walreceiver进程。主节点
postgres进程锁定事务提交过程并等待备节点响应(ACK)。备节点
walreceiver把接收到的 WAL 记录通过系统调用write()函数进行写入,并返回一个 ACK 给主节点。备节点
walreceiver通过系统调用fsync()把 WAL 记录刷盘,然后再返回一个 ACK 给主节点。备节点
startup把新刷盘的 WAL 记录进行回放。主节点
postgres进程结束等待并释放事务提交锁定,然后返回成功给客户端。这里的释放时机会根据数据库参数 synchronous_commit 的配置不同而不同,当配置为on时则在第 5 步时释放,当配置为remote_write时则在第 4 步就释放,当配置为remote_apply时则在 第 6 步完成后才释放。
没有 WAL 记录发送时备节点也会定期向主节点发送 ACK 报告自己的状态信息,这个称为 心跳检测(heart-beats),每次发送 ACK 包括如下信息:
- 备节点最新刷盘(flushed)的 LSN。
- 备节点最新写入(written)的 LSN。
- 备节点最新回放(replayed)的 LSN。
- 本次 ACK 的时间戳。
4 参考资料
[Streaming Replication] : https://www.interdb.jp/pg/pgsql11/index.html

