七八年前,老冯手里维护着一百套大规模 PostgreSQL 集群,两百多台顶配物理机,开始做高可用方案选型。 那段时间我把市面上能叫得出名字的方案都翻了一遍:Patroni、Corosync + Pacemaker、repmgr、Stolon、pgpool-II……

最后选了 Patroni。基于它做 HA,上线后效果很稳:这些年碰到几十次真实硬件故障,RTO 基本都在二三十秒区间。 最爽的是:。

回头看,这个选择属于 “少走七年弯路”。今天无论你看传统 Linux 发行版方案(Percona、AutoBase 等), 还是 K8S Operator(Crunchy PGO 等),主流 PG 发行版高可用几乎都绕不开 Patroni。 Patroni 在 GitHub 上的 Star (8.1K) 也超过其他这些 HA 组件的总和。

那么,为什么是 Patroni 成为了事实标准?它到底好在哪里? PostgreSQL 高可用到底应该怎么做?今天我们就来聊聊这个话题。

可用性,RTO与RPO

可用性 (Availability)是一个服务指标,一般用 “服务可用时间/总时间窗口” 的百分比来计算,时间窗口一般是整年或者整月。 通常 99.99% 以上的可用性(4个9)被称作高可用 —— 意味着年度故障预算 52 分钟,或月度故障预算 4.3 分钟。

但可用性是业务连续性指标,不是数据库的 技术能力。一个经典误区是:你完全可以单凭运气做到 100% 的可用性,这很常见。 云厂商承诺几个9的SLA,本质上也不是历史战绩,而是代金券对赌协议。

真正重要的是,发生故障的频率与恢复时间。对于数据库来说,你控制不了故障发生的频率(MTBF); 但你能控制的是:发生故障后最多丢多少数据,以及要多长时间恢复。这就是两个核心可靠性指标 —— RPO 与 RTO:

RPO(Recovery Point Objective,恢复点目标) : 定义了在主库发生故障时,允许丢失的最大数据量。

RTO(Recovery Time Objective,恢复时间目标) : 定义了在主库发生故障时,系统恢复写入能力所需的最长时间。

RTO 和 RPO 代表了真正 抗事的能力,也是我们考察高可用方案的关键所在。

那么 RPO / RTO 要多好才算好?这里有几个相关的国际/国家标准,规定了各个行业要求的 RPO / RTO 水平。 比如 SHARE-78,GB/T 20988-2025,SOX / HIPPA / Basel III 都对 RTO/RPO 提出了合规要求。 于今年元旦开始实行的国内的 《网络安全技术 信息系统灾难恢复规范》将灾难恢复划分为六个等级:

打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片

最高等级的容灾要求,通常要求 RTO 在分钟级(几十秒的量级),RPO = 0 不丢失数据。 十几年前,你可能要花几百万上千万采购专有软硬件来满足这样的要求。 而在 2026 年的当下,有了 Patroni + PostgreSQL,实现这种容灾水平的软件成本已经无限接近于零。

但显然,因为信息不对称,很多人并不知道这件事。所以今天我就来给大家讲讲 PostgreSQL 高可用的 SOTA 事实标准 —— Patroni。

太长不看

Patroni 在合理配置的情况下,可以轻松做到 RTO < 30s,RPO = 0 的水平,这是经过理论推演与实战检验的结果。 在 RPO 上,Patroni 可以实现 Oracle 最大性能/最大可用/最大保护模式,甚至提供了比 Oracle 最大保护模式更强的数据一致性选项。 在 RTO 上,Patroni 可以在常规硬件上实现端到端 RTO < 30s 的水平,包含从故障检测,主从切换,到负载均衡器健康检查的全链路耗时。 接下来,我们将详细介绍高可用中 RPO 与 RTO 的利弊权衡。

RPO 利弊权衡

RPO 定义了主库故障时允许丢失的最大数据量。对于金融交易这类数据完整性至关重要的场景,通常要求 RPO = 0,即不允许任何数据丢失。

然而更严格的 RPO 指标是有代价的:它会引入更高的写入延迟,降低系统吞吐量,并且存在从库故障导致主库不可用的风险。 因此对于常规场景,通常可以接受一定量的数据丢失(例如不超过 1MB),以换取更高的可用性与性能。

在异步复制场景下,从库和主库之间会存在一定的复制延迟(取决于网络和吞吐量,正常在 10KB~100KB / 100µs~10ms 的数量级)。 这意味着主库故障时,从库可能还没有完全同步最新数据。此时如果发生故障切换,新主库可能会丢失一些尚未复制的数据。

打开网易新闻 查看精彩图片

实现原理

Patroni 提供了一个参数 maximum_lag_on_failover,用于控制潜在数据丢失量的上限,默认为 1048576 (1MB)。 这意味着自动故障转移时,最多可以容忍 1MB 的数据丢失。当主库宕机时,如果有任何一个从库的复制延迟在这个值以内,Patroni 将自动提升该从库为新主库。

然而当所有从库的复制延迟都超出这个阈值时,Patroni 将拒绝进行自动故障切换以避免数据丢失。 此时需要人工介入决策:等待主库恢复(可能永远不会恢复),还是接受数据损失并强制提升一个从库。

这就引入了第一项利弊权衡:你需要根据业务需求配置这个值,在 可用性一致性 之间进行 利弊权衡。 增大这个值可以提高自动故障切换的成功率(降低不可用时长),但也会增加潜在的数据丢失量上限。

在不允许任何数据丢失的场景下,你可以使用 Patroni 的同步模式与严格同步模式,来确保 RPO = 0。

Oracle 类比

对于熟悉 Oracle 的用户来说,Patroni 的复制模式可以类比 Oracle Data Guard 提供的三种数据保护模式:最大性能、最大可用、最大保护。

打开网易新闻 查看精彩图片

实际上,通过配置 Patroni 和 PostgreSQL,你甚至可以实现比 Oracle 最大保护模式更强的数据一致性选项。 例如 Oracle Data Guard 的最大保护模式只要求一个同步从库确认写入,而 Patroni 可以配置多个同步从库确认写入, 甚至确认重放完成(remote_apply),来进一步提高数据持久性与一致性。

打开网易新闻 查看精彩图片

JEPSEN 提供了一个非常罕见的例子,我们会有一篇专门的文章详细介绍。

对于绝大多数业务来说,异步复制(最大性能)模式提供的 RPO 保证已经足够。 对于对数据完整性要求极高的场景,可以使用最大可用 / 最大保护模式来确保 RPO = 0。

RTO 利弊权衡

RTO 定义了主库故障时,系统恢复写入能力所需的最长时间。

当主库故障时,整个恢复流程涉及多个阶段:检测故障、DCS 锁过期、新主选举、执行 promote、负载均衡器感知新主库。因此不同于 RPO,RTO 不可能等于零。

而且需要注意,RTO 并非越小越好。更短的 RTO 意味着缩短各阶段的超时时间,这会使集群对网络抖动更加敏感,从而增加误切风险。 RTO 设置的太小,切换耗时虽然变短,但是误切概率上升了,切换频率增加,整体可用性反而下降了。

这就引出了第二项利弊权衡,你需要根据实际网络条件选择合适的配置,在 恢复耗时误切概率 之间取得平衡: 网络质量越差,越应该选择保守的配置;网络质量越好,越可以选择激进的配置。

关于 RTO 的营销话术

因为 RPO 这个指标没什么好吹的,RTO 已经沦为数据库营销吹牛的重灾区。有时候是拿特例场景乐观路径来以点盖面,或者在驱动 / 连接池层面排队并用统计口径做文章。因此讨论 RTO 的时候,需要明确几个因素:

故障域 :是计算节点故障,还是存储故障、网络故障?

测量口径 :可用标准是数据库可写入,还是 LB,APP,连接池/驱动层可用?

统计量 :使用的是最优值、最差值,还是平均值与中位数?

网络条件 :是同机柜、同机房、同城,还是跨大洲的全球复制?

通常来说,在同机柜网络条件中,常见故障路径下,RTO < 30s 算是业界顶级水平。 如果有人不带场景、故障域、统计口径说自己 RTO < 10 秒,通常可以判定为吹牛。

严肃的 RTO 的讨论非常复杂,在下面,我们会讨论四种典型网络条件下的参数配置,两种主要故障路径下的 RTO 拆解,以及最优,平均,最劣三种情况; 并使用更为严格的 HAPRXOY 端侧接受连接写入作为 RTO 的测量口径,如果没有特别解释,我们讨论的是用于兜底的 最劣 情况,而非平均或最优情况。

架构原理

RTO 无法脱离架构,场景,环境,资源来讨论,因此我们需要先来介绍一下基于 Patroni / Etcd / HAProxy 的经典高可用架构,在这个架构中:

打开网易新闻 查看精彩图片

•PostgreSQL 使⽤标准流复制搭建物理从库,主库故障时由从库接管。•Patroni 负责管理 PostgreSQL 服务器进程,处理高可用相关事宜。•Etcd 提供分布式配置存储(DCS)能力,并用于故障后的领导者选举•Patroni 依赖 Etcd 达成集群领导者共识,并对外提供健康检查接口。•HAProxy 对外暴露集群服务,并利⽤ Patroni 健康检查接口,自动分发流量至健康节点。

在这套架构中,高可用 RTO 主要取决于 Patroni 参数,次要取决于 Haproxy 参数。

参数配置

Patroni 中关于 RPO 的核心参数只有三个,但考虑 RTO 时,总共要纳入的参数有 10 个: Patroni 5 个,HAProxy 健康检查 5 个。这十个参数的组合决定了 RTO 的表现。

请注意,默认参数的表现并不是最优的。我在长期实践中提出了四组不同网络条件下的参数优化配置:fast、normal、slow、safe。

打开网易新闻 查看精彩图片

四种模式实际上对应着四组不同的参数配置,如下所示:

打开网易新闻 查看精彩图片

这四种模式下,RTO 的最坏,最好,平均表现水平如下图所示。

打开网易新闻 查看精彩图片

我们以最坏口径作为讨论的基准, 在默认配置下 RTO < 45s,最优模式下 RTO < 30s。 更宽容的模式则设置有 90s / 150s 的 RTO 上线目标。

这里特别需要提到的是,市面上绝大多熟 PG 高可用方案几乎都没有修改 Patroni 默认参数, 尽管默认参数在常规被动故障切换中提供 RTO < 45 秒的表现,但默认 primary_start_timeout 的 300 秒配置, 会导致 PG 主库崩溃重新拉起这个故障场景中,最劣表现高达 324 秒,违背常规的 RTO 目标。

如果你自己手搓 Patroni 高可用,这一点务必注意。

故障路径

那么这个图里的数据是怎么计算得到的呢?这里我们就要讨论 故障路径 了。

在 Patroni 这套高可用架构中,有 10 种典型故障:节点宕机 / 假活、PG 崩溃 / 拒绝连接 / 假活、Patroni 崩溃 / 假活、主库 / DCS 网络中断、存储故障等等。 这些故障总体可以划分为五条 RTO 拆解路径,在讨论最坏情况时,归并到两条典型的故障路径:

被动检测 : Patroni 挂了或者网络隔离,主库无法续租,触发集群选举

主动检测 : Patroni 活着,尝试修复 PG 挂了这种问题,超时后触发集群选举

这两种故障路径殊途同归,可以用下面的流程图表示:

打开网易新闻 查看精彩图片

这两条故障路径的 RTO 计算方式有差异,下面会简要介绍,详细完整的分析报告请参阅下面的文档: http://pigsty.cc/docs/concept/ha/failure/[1]

打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片

这里的 RTO 时序拆解,给出了 RTO 的下界和上界。 我们在设定的时候,以上界最悲观的情况设置,确保满足最严格的容灾等级要求。

考虑 平均 情况的话 fast 档位在 23-24 秒,默认 norm 档位在 34-35 秒的水平。

打开网易新闻 查看精彩图片
打开网易新闻 查看精彩图片

关于 RAC 与分布式数据库

有些数据库承诺非常低的 RTO,甚至号称秒级切换、RTO = 0。这些方案通常使用共享存储 RAC 架构,或者分布式 Raft/Paxos 协议。 但仔细推敲就会发现,这些声称往往只针对特定故障域成立,而且会因为架构上的利弊权衡引入其他局限性。

以 Oracle RAC 为例,多个计算节点访问同一个底层磁盘阵列。在实例故障时确实可以快速切换,但当底层存储出现单点故障时,RTO 就直接炸了 —— 所有节点一起完蛋。 这本质上是把复杂度和风险下推到存储层,逼着你购买价格高昂的企业级 SAN 存储来兜底。 而且真要做跨区域容灾,还是得靠 Data Guard 这类主从复制技术。然后 RTO 又回到几十秒的量级了。 所以 Oracle RAC 的营销宣传在我看来极具误导性。

一些 NewSQL 分布式数据库稍微诚实一点。比如 CockroachDB 用 Raft 协议管理多节点集群,在主要故障场景下号称 RPO = 0、RTO < 9s。 这个数字是可信的,但代价是什么?翻了几倍的写入延迟,几分之一的性能吞吐,以及更高的架构/运维复杂度。 关于这一点,老冯在《》中详细探讨过(还有《DDIA 第六章:复制》)。 说到底一切都是利弊权衡,只要你不在乎代价,AWS 开源的 pgactive PG 扩展号称能把 RTO 做到亚秒级。

相比之下,无共享架构(Shared Nothing)的思路就清爽得多:显式管理多套存储副本,每个节点都是自治的,没有存储单点。 共享存储方案很难水平扩展,而无共享架构可以轻松拉出几十个从库 —— OpenAI 1 主 40 从 ,我们在探探1主32从的 PG 集群就是这么玩的。 这也是为什么过去二十年,无共享架构逐渐成为数据库高可用的主流选择。

老冯自己的看法是,这年头鼓吹共享存储高可用方案,有大概率是为了给硬件/云盘带货。 老冯对这种事向来不感冒,本文就进一步具体展开批判了。但后面也许会专门写一篇,聊聊 RAC 与分布式数据库的真实表现与实际代价, 顺便讲讲 Corosync + Pacemaker 这种极其繁琐的老古董 PG 高可用方案为什么该进博物馆了。

关于实操

聊完原理,说说落地。我知道很多人看到这里会想:道理我都懂,但让我自己一台一台去配 Etcd、Patroni、HAProxy,俺做不到啊。

放心,老冯自己也不会干这种傻事。

我把这套 PG 高可用方案做成了开源免费、一键部署的完整解决方案:Pigsty。

打开网易新闻 查看精彩图片

你也可以用别的 —— AutoBase,Percona,各种 K8S PG Operator 也大同小异。 反正高可用部分的核心架构基本都是一样的 Patroni + etcd + Haproxy。

不过,很多用着 patroni 的方案几乎都清一色用着默认参数。 看起来没人认真优化过,也没人做过精细的 RTO 时序分析,也许是放到“企业级”方案里去了吧。 而 Pigsty 在大规模生产环境中实战打磨出来,针对不同网络条件提供了多种 RTO/RPO 策略可选, 除此之外,还内置了连接池、自动故障切换、完整的监控告警体系 —— 开箱即用不操心。

另外提醒一句:光有高可用还不够。硬件故障 Patroni 能扛,但误删数据、逻辑错误这类场景,还得靠 PITR 来兜底。 所以今天讲的是 PostgreSQL 高可用的事实标准——Patroni,后面还会介绍备份恢复的事实标准 —— pgBackRest。

朋友们,别折腾手搓 PG 高可用了!土法自建对技术成长和业务发展都没啥帮助 —— 把原理搞明白会用就行。 与其重复造轮子,不如折腾折腾怎么用好 PG 本身,这里能玩的扩展太多了,可比折腾什么 HA PITR 有意思多了。

小结

通过精细的参数调优,Patroni 的 RTO 上界可以被精确控制在不同档位。 在常规网络环境下,30 秒的 RTO 水平触手可及。 这些年我在生产环境中经历的几十次真实故障切换,监控数据显示 RTO 稳定在 20~30 秒,完全满足最严苛的金融级容灾要求。

七年前做这个选型时,Patroni 还是个小众方案。当时不少人觉得它不够"企业级",不如商业方案有保障。 现在再看,那些迷信复杂架构和昂贵软件的团队,要么还在为高可用焦头烂额,要么早就悄悄换成了 Patroni。

技术选型这件事,从来不是看谁更复杂、谁更贵,而是看谁能真正把问题解决掉。 Patroni 用最简洁的架构实现了最可靠的效果,这就是它成为事实标准的原因。