Vadim Yatsenko:在PGDay Israel 2026上的演讲:持久性、一致性与性能

Vadim Yatsenko:在PGDay Israel 2026上的演讲:持久性、一致性与性能

💡 原文英文,约400词,阅读约需2分钟。
📝

内容提要

在PGDay Israel 2026上,Alexey Kopytov介绍了阿里云PolarDB从开源项目走向生产就绪的实践。PolarDB采用存算分离架构,读写节点共享同一存储,新增只读副本无需复制数据,故障切换无需重新同步。文章围绕五个主题展开:DataMax专用WAL日志存储节点、基于LSN的读己之写一致性、零拷贝I/O、Disk-Paxos读写租约防脑裂,以及CSN无锁快照。其核心原则是绝不因吞吐量牺牲正确性。

🔎

延伸解读

存算分离如何改变扩展与故障切换

传统 PostgreSQL 集群中,每个只读副本都保存完整数据并重放整个 WAL 流,因此扩展读能力和故障切换都要付出数据复制与重同步的代价。PolarDB 让读写节点共享同一存储,新增只读副本无需复制数据,故障切换也无需重新同步。这意味着扩展读副本和切换主节点时,不再受制于数据拷贝时间,但前提是共享存储本身可靠且一致。

五个主题背后的设计取舍

文章将 PolarDB 的实践拆为五个主题:DataMax 专用 WAL 存储节点、基于 LSN 的读己之写一致性、零拷贝 I/O、Disk-Paxos 读写租约防脑裂,以及 CSN 无锁快照。它们分别对应持久性、一致性、性能、共享存储 fencing 和快照加锁问题。核心原则是绝不因吞吐量牺牲正确性,因此这些优化并非孤立性能技巧,而是围绕正确性前提展开。

读己之写为何需要等待机制

复制延迟会破坏读己之写:客户端写入后立即读副本,可能读到旧数据。PolarDB 在代理层采用基于 LSN 的等待,让副本只有在重放到足够位置后才响应读请求。这实际上把一致性问题转化为可控的等待问题,用短暂延迟换取读请求不返回过期结果。读者应关注这种等待对延迟的影响,以及它依赖 LSN 推进的准确性。

共享存储下的防脑裂与快照优化

共享存储架构必须确保同一时刻只有一个写入者。PolarDB 使用写入共享磁盘的 Disk-Paxos 读写租约,每秒续约,并由 watchdog 执行 fencing 来防止脑裂。同时,CSN 无锁快照用少量原子计数器替代 ProcArrayLock 下的 ProcArray 遍历,降低快照获取开销。这两项分别处理写入安全与读快照性能,但都依赖底层机制正确运行,不能仅凭吞吐提升判断其可靠性。

❓

Q&A

PolarDB 的存算分离架构相比传统 PostgreSQL 集群有什么优势?

传统 PostgreSQL 集群中,每个只读副本都保留完整数据副本并重放整个 WAL 流,扩展读和故障切换都要付出这个代价。PolarDB 将计算与存储分离,一个写节点和多个读节点共享同一存储,因此新增只读副本无需复制数据,故障切换也无需重新同步数据。

PolarDB 如何保证读写一致性中的“读己之写”?

PolarDB 在代理层实现基于 LSN 的等待机制:当客户端写入后发起读请求时,代理会等待只读副本重放 WAL 到足够新的 LSN,确保副本已包含该写入后才返回查询结果,从而避免因复制延迟导致读不到自己刚写的数据。

PolarDB 的 DataMax WAL 日志存储节点有什么作用?

DataMax 是一个专用的 WAL 日志存储节点,它持久化保存 WAL 的近同步副本,并将日志级联转发给其他节点,但自身从不重放 WAL 记录。这样将持久性问题首先作为日志问题处理:先存储 WAL,再决定是否重放。

PolarFS 如何防止脑裂(split-brain)?

PolarFS 采用 Disk-Paxos 读写租约机制:将锁直接写入共享磁盘,租约每秒续期一次,并由看门狗(watchdog)监控。如果写节点无法续期租约,看门狗会将其隔离(fencing),确保同一时刻只有一个写节点,从而防止脑裂。

PolarDB 的 CSN 无锁快照是如何提升性能的?

传统 PostgreSQL 获取快照需要遍历 ProcArray 并持有 ProcArrayLock,成为竞争点。PolarDB 引入提交序列号(CSN)MVCC,用几个原子计数器替代 ProcArray 遍历,实现无锁快照获取,减少锁竞争,提升高并发下的性能。

PolarDB 在零拷贝 I/O 方面做了什么优化?

PolarDB 为存储守护进程 pfsd 实现了零拷贝 I/O,移除了 WAL 路径上的最后一次数据拷贝,使共享存储守护进程直接原地写入调用者的缓冲区,从而减少不必要的内存拷贝,降低 I/O 路径开销。

PolarDB 在持久性、一致性和性能之间的核心设计原则是什么?

核心原则是绝不因吞吐量牺牲正确性。具体体现为:持久性首先是日志问题(先存 WAL 再决定重放);一致性是等待问题(证明读者已追上再回答);性能是拷贝问题(消除不必要的拷贝);共享存储是 fencing 问题(确保只有一个写者);快照是锁问题(读计数器而非遍历锁)。

🏷️

标签

➡️

继续阅读