開發與維運

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

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

作者

digoal

日期

2019-01-27

標籤

PostgreSQL , 同步 , 半同步 , 流複製


背景

兩節點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丟失 - 珍藏級》

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

《PostgreSQL 時間點恢復(PITR)在異步流複製主從模式下,如何避免主備切換後PITR恢復走錯時間線(timeline , history , partial , restore_command , recovery.conf)》

免費領取阿里雲RDS PostgreSQL實例、ECS虛擬機

大量阿里雲PG解決方案: 任意維度實時圈人; 時序數據實時處理; 時間、空間、業務 多維數據實時透視; 獨立事件相關性分析; 海量關係實時圖式搜索; 社交業務案例; 流式數據實時處理案例; 物聯網; 全文檢索; 模糊、正則查詢案例; 圖像識別; 向量相似檢索; 數據清洗、採樣、脫敏、批處理、合併; GIS 地理信息空間數據應用; 金融業務; 異步消息應用案例; 海量數據 冷熱分離; 倒排索引案例; 海量數據OLAP處理應用;

德哥的 / digoal's PostgreSQL文章入口 - 努力做成PG資源最豐富的個人blog

德哥的微信 / digoal's wechat

Leave a Reply

Your email address will not be published. Required fields are marked *