标簽
PostgreSQL , 同步 , 半同步 , 流複制
https://github.com/digoal/blog/blob/master/201901/20190127_01.md#%E8%83%8C%E6%99%AF 背景
兩節點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。立即生效 (對已有連接配接和建立連接配接都會立即生效)。
https://github.com/digoal/blog/blob/master/201901/20190127_01.md#%E6%B6%89%E5%8F%8A%E6%8A%80%E6%9C%AF%E7%82%B9 涉及技術點
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-VIEWSwait_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.
https://github.com/digoal/blog/blob/master/201901/20190127_01.md#%E5%AE%9E%E8%B7%B5 實踐
https://github.com/digoal/blog/blob/master/201901/20190127_01.md#%E7%8E%AF%E5%A2%83 環境
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'
https://github.com/digoal/blog/blob/master/201901/20190127_01.md#%E5%90%8C%E6%AD%A5%E9%99%8D%E7%BA%A7%E5%8D%87%E7%BA%A7---%E5%AE%9E%E8%B7%B5 同步降級、更新 - 實踐
關閉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();
https://github.com/digoal/blog/blob/master/201901/20190127_01.md#%E5%B0%8F%E7%BB%93 小結
1、在不修改PG核心的情況下,通過外部輔助監測和操縱(例如5秒監控間隔)),實作了兩節點的半同步模式,在雙節點或單節點正常的情況下,保證RPO=0,同時RTO可控(例如最長wait_event='SyncRep'等待時間超過10秒)。
2、核心修改建議,
降級:可以在等待隊列中加HOOK,wait_event='SyncRep'等待逾時後降級為異步。
更新:在wal_sender代碼中加hook,監測到standby恢複後,改回同步模式。
https://github.com/digoal/blog/blob/master/201901/20190127_01.md#%E5%8F%82%E8%80%83 參考
《PostgreSQL 一主多從(多副本,強同步)簡明手冊 - 配置、壓測、監控、切換、防腦裂、修複、0丢失 - 珍藏級》 《PostgreSQL 時間點恢複(PITR)在異步流複制主從模式下,如何避免主備切換後PITR恢複走錯時間線(timeline , history , partial , restore_command , recovery.conf)》https://github.com/digoal/blog/blob/master/201901/20190127_01.md#%E5%85%8D%E8%B4%B9%E9%A2%86%E5%8F%96%E9%98%BF%E9%87%8C%E4%BA%91rds-postgresql%E5%AE%9E%E4%BE%8Becs%E8%99%9A%E6%8B%9F%E6%9C%BA 免費領取阿裡雲RDS PostgreSQL執行個體、ECS虛拟機
