设计计划内主备切换,将中断降至最低

设计计划内主备切换,将中断降至最低

💡 原文英文,约1600词,阅读约需6分钟。
📝

内容提要

Neki 计划内主备切换分三步:预检、收敛与提升、客户端恢复。与故障切换不同,无需故障检测,可在主库正常时先验证分片状态、目标副本、逻辑槽和配置兼容性。切换时先让路由器缓冲写查询,再将主库设为只读,采样 WAL 位置并断开其他副本,确定最终位置后等待目标副本追平。若超时则回滚,主库恢复可写。同步复制保证已确认提交不丢失,应用仅感知延迟而非报错。

🔎

延伸解读

计划内切换与故障切换的关键差异

文章指出,计划内主备切换不需要故障检测,因为主库仍正常服务,控制面可提前完成预检。这与非计划故障切换形成对比:后者必须先确认主库是否真的失效,避免出现双主。计划切换把预检放在主库可写时进行,若检查失败则直接拒绝,主库保持不变,从而把风险控制在切换动作之前。

不关停主库如何确定最终 WAL 位置

Neki 没有像 Patroni 那样先停掉主库 Postgres,而是让路由器缓冲写查询、将主库新事务设为只读,再采样 WAL 位置并断开其他副本,取采样位置与各副本最终 receive_lsn 的较高值作为目标。这样既保留了旧主库快速回退的能力,又通过断开其他副本阻止 WAL 继续增长,使目标副本有明确的追平终点。

同步复制在切换前后的延续

文章强调,Neki 使用 ANY 1 的同步复制配置,避免单个慢副本阻塞主库。切换时,目标副本必须先刷写到采样位置,并追平断开副本记录的最高位置;提升后,至少一个已连接副本要出现在同步配置中,否则目标可能因等待确认而阻塞,此时 Admin 会回滚。旧主库随后通过相同流程变为新主库的副本,并参与同步确认。

应用侧感知与缓冲的边界

切换期间,路由器会暂存原本发往主库的查询,副本读不受影响;完成后重新规划并发送到新主库,应用只感知延迟而非报错。但缓冲并非无界:Admin 不等待所有路由器确认,缓冲容量有限且查询有截止时间,缓冲满或切换过久仍会导致查询失败。若目标副本未追平,切换有截止时间,超时后 Admin 可让旧主库恢复可写并重连其他副本。

❓

Q&A

Neki 的计划内主备切换分为哪几个阶段?

分为三个阶段:预检验证、收敛与提升、客户端恢复。预检在主库正常时进行,后两个阶段构成实际中断期。

计划内主备切换为什么不需要故障检测?

因为计划内切换已知主库将主动让位,无需像故障切换那样先确认主库是否真的失效。Admin 可利用切换前的时间检查分片和候选副本,若检查失败则拒绝切换,主库保持不变。

Neki 如何确定最终的 WAL 位置以确保安全提升副本?

Neki 先让路由器缓冲写查询,再将主库设为只读。然后采样主库 WAL 位置和副本复制状态,选择已刷写到采样位置的副本(如 R2),断开其他副本并记录各自的最终 receive_lsn,取采样位置和最高 receive_lsn 中的较大者作为最终位置,等待目标副本重放至该位置。

切换过程中如何保证同步复制不丢失已确认的提交?

Neki 配置同步复制为 ANY 1 (...),列出所有合格副本。切换时确保目标副本已刷写到采样位置,并重放断开副本的最终位置。断开其他副本后,目标副本成为唯一同步备库,任何提交必须在其刷写后才能被确认。提升后还需确保至少一个副本连接并加入同步配置,否则回滚。

计划内切换期间应用程序会感知到什么?

应用程序只会感知到查询延迟增加,而不会收到错误。路由器会缓冲发往主库的查询,切换完成后用新拓扑重新规划并发送到新主库。读查询不受影响。

如果目标副本未能追平最终 WAL 位置,Neki 会如何处理?

切换设有截止时间。若超时,Admin 通过配置重载将旧主库恢复为可写,并重新连接之前断开的副本,立即恢复服务。

预检阶段 Admin 会验证哪些内容?

Admin 会验证:分片状态(仅接受明确允许的状态,复制延迟、时间线分歧等会阻止切换)、操作员指定的目标是否可行、逻辑故障转移槽是否已复制到候选副本、候选副本的 Postgres 容量设置是否与所有副本兼容(如 max_connections 等参数不能大于旧主库)。

🏷️

标签

➡️

继续阅读