内容提要
本文讨论了分布式PostgreSQL架构的类型和权衡,包括单机架构、网络附加块存储、读取副本、云存储优化、主动-主动架构和透明分片。选择适合应用需求的架构时需要考虑性能、一致性和可用性等因素。
延伸解读
延迟如何拖累OLTP吞吐
文章指出,PostgreSQL使用同步交互协议,客户端需等待数据库响应后才能发送下一条命令。若事务平均耗时20毫秒,单个会话每秒只能处理50个事务。要提升吞吐量,必须增加并发会话,但每个会话占用内存等资源,且PostgreSQL通常限制最大会话数在数百到数千,这形成了吞吐量的硬上限。此外,持有锁的操作在等待网络往返时也会影响并发度。因此,分布式架构引入的内部网络往返会显著放大延迟对性能的影响。
网络附加存储的性能代价
网络附加块存储通过内部复制提供高耐久性和可用性,并支持快照备份和快速重建副本,但性能代价显著:现代NVMe磁盘可达100万IOPS、延迟数十微秒,而网络附加存储通常低于1万IOPS、延迟超过1毫秒,差距约两个数量级。文章建议,对大多数组织而言,耐久性和可用性收益通常超过性能损失,但需意识到PostgreSQL本可以快得多。
读副本的适用边界
读副本能线性扩展读吞吐并减轻主库负载,但主库提交写操作时通常不等待复制,导致副本始终略有延迟。这会造成“读己之写”问题,例如用户添加商品到购物车后立即读取购物车页面,若读请求落在副本上,可能看到空购物车。此外,随机负载均衡可能导致客户端在不同副本间看到不一致状态,且每个副本缓存内容相似,当工作集超出内存时会产生冗余I/O。文章建议,读副本适用于读请求超过10万/秒或读导致CPU瓶颈的场景,应避免用于依赖事务和大工作集。
分片与键值存储的取舍
透明分片(如Citus)按分片键分布数据,能高效利用多节点内存、IO和CPU,适合多租户应用或大工作集(>100GB)及计算密集型查询,但会引入更高延迟,且数据模型需调整(如唯一约束必须包含分片键),快照隔离也仅在分片级别。分布式键值存储(如Yugabyte)提供分片级故障转移和单键操作的良好扩展性,但关系表可能不存储在一起,导致连接和索引查找产生大量内部网络跳转,性能往往不如PostgreSQL或Citus。文章建议,简单应用可考虑键值存储的可用性优势,否则优先使用PostgreSQL。
Q&A
分布式 PostgreSQL 架构主要想解决单机 PostgreSQL 的哪些问题?
分布式 PostgreSQL 架构主要想解决单机架构的操作风险,包括机器故障导致的停机、磁盘故障导致的数据丢失、系统过载时难以扩展,以及存储容量受限于单块磁盘等问题。
网络附加块存储(如 EBS)在云上 PostgreSQL 中有什么优缺点?
优点是提供高持久性(内部复制)、高可用性(存储节点故障时服务仍可用)、数据库服务器可快速重新部署、磁盘可调整大小、支持快照快速备份和创建副本。缺点是磁盘延迟显著增加(从约 20 微秒到约 1000 微秒)、IOPS 大幅降低(从约 100 万降到约 1 万)、重启时崩溃恢复耗时、成本可能较高。
使用 PostgreSQL 读取副本扩展读吞吐量时需要注意哪些一致性问题?
读取副本是异步复制的,因此存在最终一致性,可能无法立即读到刚写入的数据(破坏读己之写一致性)。此外,在多个副本间负载均衡时,客户端可能看到不同状态的数据,缺乏单调读一致性。因此需要谨慎选择哪些读操作使用副本,避免依赖先前写入的读操作。
主动-主动架构(如 BDR)的主要挑战是什么?
主要挑战是更新冲突无法提前解决。多个节点可以同时接受对同一行的写入,导致提交后出现冲突(例如计数器递增丢失更新),系统没有线性历史,使得应用程序难以编写。此外,还存在读取副本的最终一致性和缺乏单调读一致性问题。
透明分片系统(如 Citus)适合哪些场景?
透明分片系统适合多租户应用(通过租户 ID 分片,使查询路由到单个分片组),也适合工作集大于 100GB 或计算密集型分析查询(如时间序列/IoT)的场景,可以并行化查询并利用所有节点的内存、IO、存储和 CPU。
分布式键值存储加 SQL 层(如 Yugabyte)与传统 PostgreSQL 相比有什么不足?
这类系统底层使用分布式键值存储,相关表和索引不一定存储在一起,导致连接、外键检查甚至简单索引查找可能产生大量内部网络跳转,延迟较高。事务保证涉及额外锁和协调,可能拖累性能。与 PostgreSQL 或 Citus 相比,性能和效率往往令人失望,且并非真正的 PostgreSQL,成熟度和优化程度较低。
选择分布式 PostgreSQL 架构时应该问自己哪些问题?
应该问:我真正想要什么?哪种架构能实现?有哪些缺点?我的应用能容忍什么(能否修改应用)?通过这些问题来权衡不同架构的利弊,因为几乎没有任何好处是免费的。