天天看點

PostgreSQL 雙節點流複制如何同時保證可用性、可靠性(rpo,rto) - (半同步,自動降級方法實踐)

背景

兩節點HA架構,如何做到跨機房RPO=0(可靠性次元)?同時RTO可控(可用性次元)?

半同步是一個不錯的選擇。

1、當隻挂掉一個節點時,可以保證RPO=0。如下:

主 -> 從(挂)    
  
主(挂) -> 從             

2、當一個節點挂掉後,在另一個節點恢複并開啟同步模式前,如果在此期間(目前)主節點也挂掉,(雖然此時從庫活了(但由于還未開啟同步模式)),則RPO>0。 如下:

主(挂) -> 從(OPEN,但是之前從挂過,并且還還未轉換為同步模式)  
  
與兩個節點同時挂掉一樣,RPO>0              

3、如何保證RTO時間可控?

我們知道,在同步模式下,事務送出時需要等待sync STANDBY的WAL複制回報,確定事務wal落多個副本再回報用戶端(從動作上來說,先持久化主,然後同步給sync從,并等待sync從的WAL 同步位點的回報),當STANDBY挂掉時,等待是無限期的,是以兩節點的同步複制,無法兼顧可用性(RTO)。那麼怎麼兼顧可用性呢?

可以對(pg_stat_activity)等待事件的狀态進行監測,如果發現同步事務等待超過一定門檻值(RTO門檻值),則降級為異步模式。

降級不需要重新開機資料庫。

3.1 改配置

3.2 reload (對已有連接配接和建立連接配接都會立即生效)。

3.3 cancel 等待信号(針對目前處于等待中的程序)。

4、降級後,什麼情況下恢複為同步模式?(更新)

同樣可以對(pg_stat_replication)狀态進行監測,當sync standby處于streaming狀态時,則可以轉換為同步模式。

更新不需要重新開機資料庫。

4.1 改配置

4.2 reload。立即生效 (對已有連接配接和建立連接配接都會立即生效)。

涉及技術點

1、事務送出參數

synchronous_commit    
    
on, remote_apply, remote_write, local               

2、同步配置參數

synchronous_standby_names     
    
[FIRST] num_sync ( standby_name [, ...] )    
ANY num_sync ( standby_name [, ...] )    
standby_name [, ...]    
    
    
ANY 3 (s1, s2, s3, s4)    
    
FIRST 3 (s1, s2, s3, s4)    
    
*  表示所有節點               

3、活躍會話,檢視事務送出時,等待事件狀态

pg_stat_activity               

等待事件

https://www.postgresql.org/docs/11/monitoring-stats.html#MONITORING-STATS-VIEWS
wait_event='SyncRep'             

4、流狀态,pg_stat_replication

sync_state='sync'             
state     
    text      
    Current WAL sender state. Possible values are:    
    
startup: This WAL sender is starting up.    
    
catchup: This WAL sender's connected standby is catching up with the primary.    
    
streaming: This WAL sender is streaming changes after its connected standby server has caught up with the primary.    
    
backup: This WAL sender is sending a backup.    
    
stopping: This WAL sender is stopping.               

實踐

環境

1、主

postgresql.conf    
    
synchronous_commit = remote_write    
wal_level = replica    
max_wal_senders = 8    
synchronous_standby_names = '*'               

2、從

recovery.conf    
    
restore_command = 'cp /data01/digoal/wal/%f %p'    
primary_conninfo = 'host=localhost port=8001 user=postgres'                

同步降級、更新 - 實踐

關閉standby,模拟備庫異常。看如何實作半同步。

模拟STANDBY恢複,看如何模拟更新為同步模式。

1、監測 pg_stat_activity,如果發現事務送出等待超過一定門檻值(RTO保障),降級

select max(now()-query_start) from pg_stat_activity where wait_event='SyncRep';                

2、檢視以上結果等待時間(RTO保障)

當大于某個門檻值時,開始降級。

注意NULL保護,NULL表示沒有事務處于 SyncRep 等待狀态。

3、降級步驟1,修改synchronous_commit參數。改成WAL本地持久化(異步流複制)。

alter system set synchronous_commit=local;               

4、降級步驟2,生效參數,RELOAD

select pg_reload_conf();               

5、降級步驟3,清空目前等待隊列(處于SyncRep等待狀态的程序在收到CANCEL信号後,從隊列清空,并提示用戶端,目前事務本地WAL已持久化,事務正常結束。)

select pg_cancel_backend(pid) from pg_stat_activity where wait_event='SyncRep';               

6、收到清空信号的用戶端傳回正常(用戶端可以看到事務正常送出)

postgres=# end;    
WARNING:  01000: canceling wait for synchronous replication due to user request    
DETAIL:  The transaction has already committed locally, but might not have been replicated to the standby.    
LOCATION:  SyncRepWaitForLSN, syncrep.c:264    
    
COMMIT               

事務的redo資訊已在本地WAL持久化,送出狀态正常。

目前會話後續的請求會變成異步流複制模式(WAL本地持久化模式(synchronous_commit=local))。

如何更新?:

7、更新步驟1,監測standby狀态,sync_state='sync'狀态的standby進入streaming狀态後,表示該standby與primary的wal已完全同步。

select * from pg_stat_replication where sync_state='sync' and state='streaming';               

有結果傳回,表示standby已經接收完primary的wal,可以進入同步模式。

8、更新步驟2,将事務送出模式改回同步模式( synchronous_commit=remote_write ,事務送出時,等sync standby接收到wal,并write。)

alter system set synchronous_commit=remote_write;               

9、更新步驟3,生效參數,RELOAD (所有會話重置synchronous_commit=remote_write,包括已有連接配接,建立的連接配接)

select pg_reload_conf();               

小結

1、在不修改PG核心的情況下,通過外部輔助監測和操縱(例如5秒監控間隔)),實作了兩節點的半同步模式,在雙節點或單節點正常的情況下,保證RPO=0,同時RTO可控(例如最長wait_event='SyncRep'等待時間超過10秒)。

2、核心修改建議,

降級:可以在等待隊列中加HOOK,wait_event='SyncRep'等待逾時後降級為異步。

更新:在wal_sender代碼中加hook,監測到standby恢複後,改回同步模式。

參考

《PostgreSQL 一主多從(多副本,強同步)簡明手冊 - 配置、壓測、監控、切換、防腦裂、修複、0丢失 - 珍藏級》 《PostgreSQL 時間點恢複(PITR)在異步流複制主從模式下,如何避免主備切換後PITR恢複走錯時間線(timeline , history , partial , restore_command , recovery.conf)》

PostgreSQL 許願連結

您的願望将傳達給PG kernel hacker、資料庫廠商等, 幫助提高資料庫産品品質和功能, 說不定下一個PG版本就有您提出的功能點. 針對非常好的提議,獎勵限量版PG文化衫、紀念品、貼紙、PG熱門書籍等,獎品豐富,快來許願。

開不開森

.

9.9元購買3個月阿裡雲RDS PostgreSQL執行個體

PostgreSQL 解決方案集合

上一篇: ECS訓練營Day3
下一篇: Docsify 安裝