唯讀節點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進程處理過程。
Postmaster進程發現trigger file檔案或者接收到OnlinePromote命令後,進入OnlinePromote處理流程。
發送SIGTERM訊號給當前所有Backend進程。
說明唯讀節點在OnlinePromote過程中可以繼續提供唯讀服務,但是唯讀資料不能保證是最新的。為了避免切換過程中從新的主庫節點讀到舊的資料,這裡需要先將所有的Backend會話斷開,等Startup進程退出後再開始對外提供讀寫服務。
重新以讀寫入模式掛載共用儲存。
說明需要底層儲存提供相應的功能支援。
發送SIGUSR2訊號給Startup進程,通知其結束回放並處理OnlinePromote操作。
發送SIGUSR2訊號給Polar Worker輔助進程,通知其停止對於部分LogIndex資料的解析,因為這部分LogIndex資料只對於正常運行期間的Replica節點有用處。
發送SIGUSR2訊號給LogIndex BGW(Background Ground Worker)後台回放進程,通知其處理OnlinePromote操作。
具體過程如下圖:
Startup進程處理過程。
Startup進程回放完所有舊主庫節點產生的WAL日誌,產生相應的LogIndex資料。
確認舊主庫節點最後一次的checkpoint在Replica節點也完成,目的是確保對應的checkpoint應該在Replica節點本地寫入的資料落盤完畢。
等待確認LogIndex BGW進程進入POLAR_BG_WAITING_RESET狀態。
將Replica節點本地的資料(如clog等)拷貝到共用儲存中。
重設WAL Meta Queue記憶體空間,從共用儲存中重新載入slot資訊,並重新設定LogIndex BGW進程的回放位點為其與當前一致性位點兩者的最小值,用來表示接下來LogIndex BGW進程從該位點開始新的回放。
將節點角色設定為主庫節點,並設定LogIndex BGW進程的狀態為POLAR_BG_ONLINE_PROMOTE,至此叢集可以對外提供讀寫服務。
具體過程如下圖所示:
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進程接收到Postmaster的SIGUSR2訊號後,執行OnlinePromote操作的流程如下:
將所有的LogIndex資料落盤,並切換狀態為POLAR_BG_WAITING_RESET。
等待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都落盤了,才將一致性位點向前推進。