Ahsan Hadi:在分布式 PostgreSQL 集群上实现零停机滚动式 PostgreSQL 大版本升级

Ahsan Hadi:在分布式 PostgreSQL 集群上实现零停机滚动式 PostgreSQL 大版本升级

💡 原文英文,约2600词,阅读约需10分钟。
📝

内容提要

文章介绍用Spock多主逻辑复制实现PostgreSQL零停机大版本升级:逐节点新建新版本节点,用Zodan的add_node加入集群并同步数据,验证双向复制后迁移流量,再用remove_node下线旧节点。需注意关闭DDL复制时新表未加入复制集、Spock槽需设failover、Patroni会覆盖Spock配置等问题。

🔎

延伸解读

零停机升级的关键:多主逻辑复制

文章利用Spock多主逻辑复制,让每个节点都能接受写入,从而避免传统pg_upgrade需要停机的痛点。升级时逐个添加新版本节点,迁移流量后再下线旧节点,应用始终有可写端点。但需注意,这并非完全无中断:关闭DDL复制期间不能进行模式变更,且新节点加入后必须手动复制复制集成员,否则写入不会传播。

易被忽略的配置陷阱

作者在测试中遇到三个隐蔽问题:关闭DDL复制后,新节点的表未加入复制集,导致单向复制且状态检查仍显示健康;Spock槽默认failover=false,需手动改为true才能参与槽同步;Patroni会覆盖Spock所需参数,必须将wal_level、shared_preload_libraries等写入etcd配置。这些陷阱不会在常规状态检查中暴露,需通过双向写入测试验证。

备节点与故障转移的权衡

旧节点的物理备节点不升级,而是从新版本节点用pg_basebackup重建,由Patroni自动完成。为保障故障转移后复制不丢失,需将Spock槽标记为failover,并设置synchronized_standby_slots,使主节点等待备节点收到WAL后再发送给其他节点。代价是备节点宕机时,主节点会暂停向其他Spock节点发送变更,直到备节点恢复。

❓

Q&A

如何在不中断应用的情况下对分布式PostgreSQL集群进行大版本升级?

使用Spock多主逻辑复制,逐节点添加新版本节点,通过Zodan的add_node加入集群并同步数据,验证双向复制后迁移流量,再用remove_node下线旧节点。整个过程应用始终有可写节点。

Spock的add_node在升级过程中具体做了什么?

add_node会从现有节点复制模式和数据到新节点,并在所有节点之间建立双向订阅,同时集群继续接受写入。它还会检查Spock版本和角色是否匹配。

升级时关闭DDL复制后,新节点上的表为什么不会自动加入复制集?

因为DDL复制关闭后,新节点上创建的表不会自动加入复制集,导致新节点只接收变更但不发布任何变更。需要手动从源节点复制复制集成员关系,使用spock.repset_add_table添加表。

新节点上的Spock复制槽需要设置failover吗?为什么?

需要。add_node创建的复制槽默认failover=false,原生槽同步会跳过这些槽,导致故障转移后其他节点丢失复制位置。必须在暂停订阅的情况下将槽的failover改为true。

Patroni会覆盖Spock的配置吗?如何避免?

会。Patroni接管节点后会用自身默认值替换Spock所需配置(如shared_preload_libraries、wal_level等)。必须将所有Spock要求添加到Patroni的etcd集群配置中,然后重启节点。

升级后如何下线旧节点?

在旧节点上运行zodremove.sql并调用spock.remove_node,它会删除该节点的订阅、复制集和集群注册信息。之后确认剩余节点不再列出该节点且无残留复制槽。

🏷️

标签

➡️

继续阅读