文档

只读节点Online Promote

更新时间:

只读节点Online Promote机制是PolarDB PostgreSQL版将只读备库节点提升为主库节点的一种Promote能力。

前提条件

支持的PolarDB PostgreSQL版的版本如下:

  • PostgreSQL 14(内核小版本14.5.1.0及以上)

  • PostgreSQL 11(内核小版本1.1.1及以上)

说明

您可通过如下语句查看PolarDB PostgreSQL版的内核小版本的版本号:

  • PostgreSQL 14

    select version();
  • PostgreSQL 11

    show polar_version;

背景信息

PolarDB PostgreSQL版是基于共享存储的一写多读架构,与传统数据库的主备架构有以下不同:

  • Standby节点:是传统数据库的备库节点,有独立的存储,与主库节点之间通过传输完整的WAL日志来同步数据。

  • 只读节点:Replica节点,是PolarDB PostgreSQL版的只读备库节点,与主节点共享同一份存储,与主库节点之间通过传输WAL Meta日志信息来同步数据。

传统数据库支持Standby节点升级为主库节点的Promote操作,在不重启的情况下,提升备库节点为主库节点,可以继续提供读写服务,保证了集群高可用的同时,也有效降低了实例的恢复时间RTO。

PolarDB PostgreSQL版同样需要只读备库节点提升为主库节点的Promote能力,鉴于只读节点与传统数据库Standby节点的不同,PolarDB PostgreSQL版推出了一写多读架构下只读节点的OnlinePromote机制。

使用指南

使用pg_ctl工具对Replica节点执行Promote操作:

pg_ctl promote -D [datadir]

原理介绍

OnlinePromote原理触发机制。

  • 触发机制。

    PolarDB PostgreSQL版使用和传统数据库一样的备库节点Promote方法,触发条件如下:

    • 调用pg_ctl工具的Promote命令,pg_ctl工具会向Postmaster进程发送信号,接收到信号的Postmaster进程再通知其他进程执行相应的操作,完成整个Promote操作。

    • recovery.conf中定义trigger file的路径,其他组件通过生成trigger file来触发。

    说明

    相比于传统数据库Standby节点的Promote操作,PolarDB PostgreSQL版Replica节点的OnlinePromote操作需要考虑以下几个问题:

    • Replica节点OnlinePromote为主库节点后,需要以读写模式重新挂载共享存储。

    • Replica节点会在内存中维护一些重要的控制信息,这些控制信息在主库节点上会被持久化到共享存储中。Promote过程中,这部分信息也需要持久化到共享存储。

    • Replica节点在内存中通过日志回放得到的数据信息,在OnlinePromote的过程中需要确认哪些数据可以写入共享存储。

    • Replica节点在内存中回放WAL日志时,缓冲区淘汰方法和不刷脏的特性与主库节点截然不同,OnlinePromote过程中应该如何处理。

    • Replica节点OnlinePromote过程中,各个子进程的处理过程。

  • Postmaster进程处理过程。

    1. Postmaster进程发现trigger file文件或者接收到OnlinePromote命令后,进入OnlinePromote处理流程。

    2. 发送SIGTERM信号给当前所有Backend进程。

      说明

      只读节点在OnlinePromote过程中可以继续提供只读服务,但是只读的数据不能保证是最新的。为了避免切换过程中从新的主库节点读到旧的数据,这里需要先将所有的Backend会话断开,等Startup进程退出后再开始对外提供读写服务。

    3. 重新以读写模式挂载共享存储。

      说明

      需要底层存储提供相应的功能支持。

    4. 发送SIGUSR2信号给Startup进程,通知其结束回放并处理OnlinePromote操作。

    5. 发送SIGUSR2信号给Polar Worker辅助进程,通知其停止对于部分LogIndex数据的解析,因为这部分LogIndex数据只对于正常运行期间的Replica节点有用处。

    6. 发送SIGUSR2信号给LogIndex BGW(Background Ground Worker)后台回放进程,通知其处理OnlinePromote操作。

    具体过程如下图:Postmaster进程处理过程

  • Startup进程处理过程。

    1. Startup进程回放完所有旧主库节点产生的WAL日志,生成相应的LogIndex数据。

    2. 确认旧主库节点最后一次的checkpoint在Replica节点也完成,目的是确保对应的checkpoint应该在Replica节点本地写入的数据落盘完毕。

    3. 等待确认LogIndex BGW进程进入POLAR_BG_WAITING_RESET状态。

    4. 将Replica节点本地的数据(如clog等)拷贝到共享存储中。

    5. 重置WAL Meta Queue内存空间,从共享存储中重新加载slot信息,并重新设置LogIndex BGW进程的回放位点为其与当前一致性位点两者的最小值,用来表示接下来LogIndex BGW进程从该位点开始新的回放。

    6. 将节点角色设置为主库节点,并设置LogIndex BGW进程的状态为POLAR_BG_ONLINE_PROMOTE,至此集群可以对外提供读写服务。

    具体过程如下图所示:Startup进程处理过程

  • LogIndex BGW进程处理过程。

    LogIndex BGW进程有自己的状态机,在其生命周期内,一直按照该状态机运行,具体每个状态机的操作内容如下:

    参数

    说明

    POLAR_BG_WAITING_RESET

    LogIndex BGW进程状态重置,通知其他进程状态机发生变化。

    POLAR_BG_ONLINE_PROMOTE

    读取LogIndex数据,组织并分发回放任务,利用并行回放进程组回放WAL日志,该状态的进程需要回放完所有的LogIndex数据才会进行状态切换,最后推进后台回放进程的回放位点。

    POLAR_BG_REDO_NOT_START

    表示回放任务结束。

    POLAR_BG_RO_BUF_REPLAYING

    Replica节点正常运行时,进程处于该状态,读取LogIndex数据,按照WAL日志的顺序回放一定量的 WAL日志,每回放一轮,便会推进后台回放进程的回放位点。

    POLAR_BG_PARALLEL_REPLAYING

    LogIndex BGW进程每次读取一定量的LogIndex数据,组织并分发回放任务,利用并行回放进程组回放WAL日志,每回放一轮,便会推进后台回放进程的回放位点。

    具体过程如下图所示:

    LogIndex BGW进程处理过程

    LogIndex BGW进程接收到Postmaster的SIGUSR2信号后,执行OnlinePromote操作的流程如下:

    1. 将所有的LogIndex数据落盘,并切换状态为POLAR_BG_WAITING_RESET

    2. 等待Startup进程将其切换为POLAR_BG_ONLINE_PROMOTE状态。

      • Replica节点在执行OnlinePromote操作前,后台回放进程只回放在buffer pool中的页面。

      • Replica节点处于OnlinePromote过程中时,鉴于之前主库节点可能有部分页面在内存中,未来得及落盘,所以后台回放进程按照日志顺序回放所有的WAL日志,并在回放后调用MarkBufferDirty,标记该页面为脏页,等待刷脏。

      • 回放结束后,推进后台回放进程的回放位点,然后切换状态为POLAR_BG_REDO_NOT_START

  • 刷脏控制。

    每个脏页都带有一个Oldest LSN,该LSN在FlushList里是有序的,目的是通过这个LSN来确定一致性位点。

    Replica节点在OnlinePromote过程后,由于同时存在着回放和新的页面写入,如果像主库节点一样,直接将当前的WAL日志插入位点设为Buffer的Oldest LSN,可能会导致:比它小的 Buffer 还未落盘,但新的一致性位点已经被设置。

    所以Replica节点在OnlinePromote过程中需要面对两个问题:

    • 旧主库节点的WAL日志回放时,如何给脏页设置Oldest LSN。

    • 新主库节点产生的脏页如何设置Oldest LSN。

    说明

    PolarDB PostgreSQL版在Replica节点OnlinePromote的过程中,将上述两类情况产生的脏页的Oldest LSN都设置为LogIndex BGW进程推进的回放位点。只有当标记为相同Oldest LSN的Buffer都落盘了,才将一致性位点向前推进。