PostgreSQL同步复制和异步复制的区别
在PostgreSQL中,主库(Primary)和备库(Standby)之间的数据同步是通过传递WAL(Write-Ahead Log,预写式日志)来实现的。
同步复制(Synchronous Replication)和异步复制(Asynchronous Replication)最根本的区别在于:当客户端发起 COMMIT(提交事务)时,主库是否需要等待备库的确认才向客户端返回成功。
以下是两者的详细对比和原理解析:
1. 核心机制对比
异步复制(Asynchronous Replication)- 默认模式
- 工作流程:
- 客户端向主库发起
COMMIT。 - 主库将事务写入本地的 WAL 日志并落盘。
- 主库立即向客户端返回“提交成功”。
- 主库在后台将 WAL 日志通过网络异步发送给备库。
- 备库接收并应用这些日志。
- 客户端向主库发起
- 特点:主库的事务提交完全不依赖于备库的状态。
同步复制(Synchronous Replication)
- 工作流程:
- 客户端向主库发起
COMMIT。 - 主库将事务写入本地的 WAL 日志并落盘。
- 主库将 WAL 日志发送给备库。
- 主库进入等待状态(阻塞),直到收到备库发来的“已接收并处理该 WAL”的确认信号(ACK)。
- 主库收到备库确认后,才向客户端返回“提交成功”。
- 客户端向主库发起
- 特点:主库必须等待至少一个(或指定数量的)备库确认,才能完成事务。
2. 优缺点与适用场景
| 维度 | 异步复制 (Async) | 同步复制 (Sync) |
|---|---|---|
| 数据安全性 (RPO) | 有数据丢失风险。主库宕机时,若有WAL尚未发给备库,这部分数据会丢失。 | 零数据丢失 (RPO=0)。返回给客户端成功的事务,一定已经安全到达了备库。 |
| 性能与延迟 | 极高。不受网络延迟和备库性能影响。 | 较低。事务延迟 = 主库处理时间 + 网络往返延迟 + 备库处理时间。 |
| 可用性 (主库抗风险能力) | 高。备库宕机、网络断开不会影响主库的正常读写。 | 低(若配置不当)。如果备库宕机或网络中断,主库的写操作会一直挂起(阻塞),直到备库恢复。 |
| 数据一致性 | 最终一致性(主备之间存在延迟/Lag)。 | 强一致性(取决于同步级别)。 |
| 适用场景 | 普通业务、读写分离、异地灾备(容忍延迟)、对性能要求极高的系统。 | 金融交易、订单支付、核心账务等绝对不允许丢失数据的系统。 |
3. PostgreSQL特有的“同步级别” (synchronous_commit)
PostgreSQL 的同步复制非常灵活,可以通过配置 synchronous_commit 参数来决定主库等待备库执行到哪一步才算成功。这也是面试中经常考察的重点:
off/local:本质上是异步。local表示只要主库自己写完本地磁盘就返回成功。remote_write:备库回复:“我已经收到 WAL 日志,并写入了操作系统的缓存中(还没刷入磁盘)。”- 风险:如果备库服务器断电,可能会丢数据;但如果只是 PostgreSQL 进程崩溃,数据不会丢。延迟较低。
on(默认的同步模式):备库回复:“我已经收到 WAL 日志,并且确确实实写入了备库的磁盘中。”- 保障:即使备库断电也能保证数据不丢,是标准的强同步。
remote_apply:备库回复:“我已经收到 WAL、写入磁盘,并且*已经应用(Apply)到了数据库中。”*- 保障:不仅保证数据不丢,还保证客户端立刻去备库查询,绝对能查到这条最新数据(强读写一致性)。延迟最大。
4. 如何克服同步复制“主库被阻塞”的缺点?
同步复制最大的隐患是单点故障导致主库阻塞(如果唯一的备库挂了,主库也无法写入了)。
PostgreSQL 提供了以下解决方案:
配置多个备库 (Quorum-based Sync Replication):
通过synchronous_standby_names参数配置多个备库。例如:synchronous_standby_names = 'ANY 1 (standby1, standby2)'
这表示:只要standby1和standby2中有任何一个确认了,主库就放行。这样挂掉一个备库,主库依然可以正常写入。优雅降级(需借助外部高可用组件):
通常配合 Patroni 等高可用工具,当检测到所有同步备库都不可用时,自动将主库的同步模式降级为异步模式,优先保证业务可用性(牺牲部分数据安全性)。
总结建议
- 绝大多数场景(90%以上):使用异步复制。利用它的高性能,并通过监控工具(如 Prometheus)严密监控 Replication Lag(复制延迟),将延迟控制在毫秒级。
- 核心资产/资金场景:使用同步复制(通常配置为
on),但必须配备至少一主两备(1 Master + 2 Sync Standbys),以防备库故障拖死主库。