20.3 同步策略与提交语义
同步复制不是一个 on/off 开关,而是提交必须等谁、等到哪一步、没有合格
副本时宁愿阻塞还是退化的合同。
在调整参数前,先回答:
20.3.1 异步、同步与远程应用确认
两个参数回答两个问题
PostgreSQL 同步复制的核心分工:
如果 synchronous_standby_names='',没有 synchronous standby;即使
session 的 synchronous_commit=on,也只完成本地提交语义,不会凭空等一
台远端。
本章正式 baseline:
synchronous_commit=on 在这里不能被误读成“同步复制已开启”。
acknowledgement levels
简化比较:
synchronous_commit |
primary 等待点 | 远端保证(有同步 standby 时) | 典型代价 |
|---|---|---|---|
off |
不等本地 WAL durable flush | 无 | 最低延迟,进程/OS crash 可丢近期提交 |
local |
本地 durable flush | 不等 remote | 本地 durability |
remote_write |
remote 写到 OS | 未要求 remote durable flush | 较低跨网延迟、保证较弱 |
on |
remote durable flush | 同步 standby WAL 已落盘 | 至少网络 RTT 与 remote storage |
remote_apply |
remote replay | standby 查询可见 | 最大等待,受 replay 影响 |
PostgreSQL 18 可配置的值只有表中的五种;on 就表示等待同步备库持久化
flush。不要把内部等待阶段或监控标签中的 remote_flush 当成可设置参数。
具体行为以当前版本
官方参数文档
为准。
remote_apply 解决可见性,不自动解决路由
当同步 standby replay 后才放行 commit,应用随后若读到同一 standby, 更容易获得 read-your-writes。但仍需:
remote_apply 不是把所有 replica 都变成线性一致读。
commit 等待与 transaction 生命周期
top-level commit 等同步确认时:
- transaction locks 仍可能影响其他 session;
- write latency 增加;
- remote storage/network jitter 进入 tail latency;
- timeout/connection loss仍可能造成 outcome unknown;
- read-only transaction 与 rollback 不需要相同等待。
同步复制把数据保护成本放进前台写路径。它没有消除成本,只是把风险从 “故障时可能丢”移动到“正常时更慢、故障时可能不可写”。
session 可以覆盖
synchronous_commit 可按系统、database、role、session 或 transaction
设置:
这允许分层:
但 policy 不能只靠开发者“记得 SET”。建议把 role/database defaults、 connection initialization、审计和测试组合起来。
如何观察
sync_state 可见当前 connection 是 async、potential、sync 或
quorum 等状态。配置意图必须回到 live view。
20.3.2 多副本同步集合与退化条件
FIRST:优先级集合
含义:
适合有明确低延迟/placement 优先级的场景。缺点是高优先级节点的性能与 抖动更容易决定写 tail。
ANY:quorum 集合
含义:
ANY 2 (...) 则等任意两个。它可以降低单个慢节点对 latency 的影响,
但数据保护与 failover candidate 必须按 quorum history 推理。
数量不是 durability 的全部
考虑:
等任意一个,通常可能总由同 AZ 的低延迟 standby 确认。若 AZ-a 整体 消失,AZ-b standby 是否一定拥有所有 acknowledged commits,需要根据实际 选择集合和时间分析。
所以配置应连接 placement:
三者未必相同。
Patroni synchronous mode
PostgreSQL 负责 commit wait;Patroni 还要管理 promotion eligibility 与 standby 集合变化。
简化:
准确行为随 Patroni 版本与 dynamic config 变化,应以 Replication modes 为准。
这体现两个目标:
无法无条件同时最大化。
退化必须是显式政策
副本不可用时的选择:
| 政策 | write availability | acknowledged data protection |
|---|---|---|
| strict block | 降低 | 保持目标 |
| controlled async degrade | 保持 | 降低,必须告警/批准 |
| manual bypass | 操作者决定 | 可能破坏 guarantee |
| reject critical, allow lower tier | 分级 | 分级 |
不要让“超时太多,先改成 async”成为无记录的事故操作。需要:
nosync、nofailover 与 placement intent
某些 standby 不应承担同步或提升角色:
HA manager tags 可以表达候选意图。但标签只是 declaration,仍要验证 live role、routing 和 performance。一个 offline tag 不能代替资源隔离。
多副本并不自动等于多份 durable commit
某一时刻:
不代表每次 commit 都等待它 durable flush。要看:
同样,“两台 sync”也不证明它们位于独立 failure domain。
candidate eligibility
选主至少考虑:
本章 baseline:
因此本章不会把 maximum_lag_on_failover 误写成 zero-loss guarantee。
Patroni 官方说明实际 worst-case 还受采样周期与近期 WAL generation 影响。
20.3.3 延迟、可用性和数据保护的交换
一个不可回避的三角
粗略地:
不能在所有故障条件下同时无代价最大化。
同步 commit latency 下界近似包含:
若 remote_apply,还要加入 replay queue 与 conflict。
P50 不够
同步写路径把远端 tail 带入本地 transaction:
需要看:
平均 RTT 很漂亮,也可能因为偶发 5 秒 stall 让 checkout 大面积超时。
timeout 不等于 rollback
即使同步 commit 等待超时或连接中断,事务可能已经:
- 在 primary durable;
- 在 standby durable;
- 只是应答未到客户端。
应用仍需 token/reconciliation。同步复制提高 durability,不消除 distributed commit outcome uncertainty。
业务分层
示例:
| 写入类 | 丢失代价 | latency tolerance | 建议方向 |
|---|---|---|---|
| 账务事实 | 极高 | 可接受更高 | strict sync + independent domains |
| 订单状态 | 高 | 中 | sync 或 durable event contract |
| clickstream | 可重建 | 低 | async/batched |
| cache projection | 可重建 | 低 | async |
| admin migration | 高 | maintenance | explicit stronger setting |
这不是固定答案。关键是同一 service 内可能需要不同 acknowledgement class。
用 decision record 替代参数清单
参数必须从 decision 推导;否则升级或换平台时只剩一堆无法解释的数。
本章为什么保留 async baseline
把沙箱临时改成 sync,可能让实验数据更“好看”,却掩盖第 19 章真实交付的 policy。我们选择:
正式结果:
它是有价值的 commit evidence,但不能越过 EX20-ASYNC-BASELINE。
从目标反推策略
决策顺序:
- 定义具体 failure scenario;
- 定义哪些 acknowledgment 不能丢;
- 映射独立 failure domains;
- 选择同步集合和 acknowledgement level;
- 决定失去 standby 时 block 还是 degrade;
- 约束 candidate 和 manual override;
- 预算正常/故障 latency;
- 让 client 支持 timeout、unknown 与 idempotency;
- 用故障演练验证;
- 用 production observation 持续校准。
不要从 synchronous_mode: true 反推业务目标。
评审问题
任何一个“以后再说”,都会在事故中变成临时一致性模型。
小结
权威参考
- PostgreSQL 18:Synchronous Replication
- PostgreSQL 18:Replication Settings
- PostgreSQL 18:WAL Settings
- Patroni:Replication modes
- 本章实际策略合同
上一节:物理流复制 · 返回本章目录 · 下一节:选主、DCS 与防脑裂 · 查看全书目录 · 查看索引中心