Postgresql管理系列-第十一章 流複製管理

同步流複製是是從9.1版本實現的,可以是一主多從的模式,在postgresql裏主叫master,備節點叫standby

主備是基於日誌傳送的技術實現同步,主節點持續發送wal數據,備節點重放接受到的wal數據

主要介紹以下幾個話題

  1. 流複製如何啓動的
  2. 主備之間如何傳送數據 
  3. 主節點如何管理多個備節點
  4. 主節點如何發現失敗的備節點

 

一.開始流複製
在流複製中,三個進程協同工作,walsender在主節點發送wal數據到備節點,然後,備節點啓動一個walreceiver和一個startup進程接受和重放數據,walsender和walreceiver通過一個TCP通訊協議建立連接
這一章節,我們將探索流複製的start-up順序,明白這些進程是如何啓動,以及如何建立連接。

1.啓動主節點和備節點
2.備節點啓動startup進程
3.備節點啓動walreceiver進程
4.walreceiver發送一個連接請求到主節點,如果主節點沒有運行,walreceiver會週期性的發送請求
5.當主節點接受到一個連接的請求,就會啓動一個walsender進程建立連接
6.walreceiver發送備節點最後的LSN,這個階段在IT領域叫握手機制
7.如果備機點的LSN小於主節點的LSN,walsender發送wal數據,即從節點的LSN到主節點LSN的wal數據,wal數據由存儲在主節點的pg_xlog(10版本以後叫pg_wal)目錄下的wal segment提供,這個階段就是備節點追趕主節點的階段
8.流複製開始工作

每一個walsender進程在和walreceiver建立連接工作都會有一個合適的狀態,以下是可能的狀態
start-up:見上圖5~6
catch-up:上圖7
streaming:上圖8
backup:因爲備份發送整個數據庫集羣的文件,比如pg_basebackup工具
通過 pg_stat_replication視圖可以查看

testdb=# SELECT application_name,state FROM pg_stat_replication;
 application_name |   state
------------------+-----------
 standby1         | streaming
 standby2         | streaming
 pg_basebackup    | backup
(3 rows)

如果備節點在停庫長時間後,再啓動會發生什麼呢?
在9.3以前,如果備節點請求的wal segments在主節點已經被覆蓋,那麼備節點無法追上主節點,對於這個問題,沒有什麼可靠的方法,但是把wal_keep_segments參數增大,可以減少這種事件的發生的可能性,這只是一個臨時措施。
在9.4以後,這個問題可是使用replication slot來預防。replication slot是一項擴展wal數據發送靈活性的特性,主要用於邏輯複製,並且提供這種問題的解決方法,即暫時回收進程,將包含pg_xlog下未發送的wal segments保存在複製槽中。

二.流複製如何處理
流複製有兩個方面:日誌傳送和數據同步,日誌傳送顯然其中一個方面,因爲流複製是基於日誌傳送的,不管何時發生寫入,主節點都會發送wal到已連接的備節點,同步複製需要數據庫同步,主節點和多個備節點同步數據
爲了準確理解流複製的工作原理,我們應該研究一個主節點如何管理多個備節點。爲了更容易理解,本節描述了一個主節點和一個備節點的情況,下一節介紹一個主節點和多個備節點的情況

主節點和同步備節點如何通訊的
假設在備節點配置了以下參數
synchronous_standby_names = 'standby1'
hot_standby = off
wal_level = archive

在自動提交模式下,假設後臺進程在主節點發出了一條insert操作,後臺進程開始一個事務,並且發出一條insert語句,並且立即提交事務,讓我們進一步探討如何完成此次提交

1.後臺進程通過執行XLogInsert()和 XLogFlush()函數將wal數據寫入並刷新到wal segment.
2.walsender進行將寫入wal segment的wal數據發送到walreceiver進程.
3.主節點發送wal數據後,後臺進程等待從備節點的ACK響應,更確切的說,後臺進程執行內部函數SyncRepWaitForLSN()來獲取latch鎖,並等待鎖釋放.
4.備節點的walreceiver進程使用write()函數將wal數據寫入到wal segment,並且返回ACK響應給walsender.
5.備節點的walreceiver進程使用fsync()函數將wal數據全部刷新到wal segment,並且返回又一個ACK響應給walsengder,通知startup進程wal已經更新.
6.starup進程回放已經寫入wal segment的wal數據.
7.walsender進程在接受到ACK響應後釋放latch鎖,然後,後臺進程提交或者終止的操作就完成了.latch釋放的時間依賴於參數synchronous_commit,如果參數是on,則在以上第五步接受ACK響應後釋放latch,如果設置是remote_write,那麼在第四步接受ACK響應後就釋放latch.
 

備節點發送主節點每一個ACK包含以下內容:
已經寫入的最新WAL數據的LSN的位置
已經刷新最新的WAL數據的LSN的位置
startup進程最新回放wal數據的LSN位置
發送ACK的時間戳

walreceiver不僅在寫入和刷新的WAL數據的時候發送ACK響應,而且還定期作爲備節點的心跳發送ACK響應。因此,主節點始終掌握所有備節點的狀態.
心跳發送間隔通過wal_receiver_status_interval設置,默認10秒.

通過以下查詢可以看到相關LSN的信息

testdb=# SELECT application_name AS host,
        write_location AS write_LSN, flush_location AS flush_LSN, 
        replay_location AS replay_LSN FROM pg_stat_replication;

   host   | write_lsn | flush_lsn | replay_lsn 
----------+-----------+-----------+------------
 standby1 | 0/5000280 | 0/5000280 | 0/5000280
 standby2 | 0/5000280 | 0/5000280 | 0/5000280
(2 rows)

 

當失敗發生時的行爲反應
在這一章,描述同步流複製的備節點故障是,主節點是如何的表現,以及如何處理這種情況.
即使同步流複製的備節點發生故障,並且不能夠給主節點返回ACK響應,主節點也會繼續等待ACK響應.因此,在主節點運行的事物無法提交,後續的查詢也無法執行。換句話說,主節點所有的操作都是停止的.(流複製不支持由於超時而自動轉到異步流複製的函數)

有兩種方法避免這種情況的發生,其中之一就是提供多臺備節點來提高系統的可用性,另一個就是通過手動執行以下步驟從同步流複製轉換到異步流複製
1.設置以下參數爲空串
synchronous_standby_names = ''
2.執行reload命令重載配置文件
pg_ctl -D $PGDATA reload
以上操作對已經連接的客戶端沒有影響,主節點會繼續處理所有連接的session的事物。

三.管理多個備節點
主節點提供所有備節點的sync_priority和sync_state,並依靠這些值來處理備節點。主節點即使管理一個節點也會也會提供這些值,在上一節中沒有提到這一點.
sync_priority表示在同步模式下備節點的優先級,是一個固定值。越小的值優先級越高,0表示異步模式,備節點的優先級按synchronous_standby_names順序列出,例如,以下配置中standy1和standy2的優先級分別是1和2.
synchronous_standby_names = 'standby1, standby2'
此參數未列出的的備節點是異步模式,優先級的值爲0.
sync_state表示備節點的狀態,這個值根據所有備節點的運行狀態以及優先級發生變化.
Sync是所有同步模式下備節點最高優先級
Potential是所有備節點中第二高的優先級級別,如果最高優先級的備節點故障,那麼這個節點會代替故障節點變爲最高優先級的備節點.
async異步模式的固定值,主節點以potential一樣的看待這個異步備節點,但是sync_state不會是sync和potential狀態.

可以通過以下視圖查看這兩個值
testdb=# SELECT application_name AS host, 
         sync_priority, sync_state FROM pg_stat_replication;
   host   | sync_priority | sync_state
----------+---------------+------------
 standby1 |             1 | sync
 standby2 |             2 | potential
(2 rows)

 

主如何管理多個備節點
主節點會等待單個同步模式下的備節點ACK響應,換句話說,主節點只確認同步流複製的寫和刷新的wal數據.因此,流複製僅僅確定同步流複製備節點與主節點處於一致和同步狀態。

這裏standby1和standby2的sync_state分別是sync和potentail.
1.從potentail備節點接受ACK響應,主節點的後端進程持續等待同步流複製備節點的ACK響應
2.主節點後端進程釋放latch,完成當前的事物處理.
相反的例子,主節點立即完成當前事物提交,而不確定potentail狀態的備節點是否寫入和刷新了wal數據.

 

發生故障時的行爲
當potentail狀態的備節點和異步流複製備節點發生故障後,主節點會終止連接到故障備節點的walsender進程,並進行自己所有的事物處理,換句話說,主節點的事務處理不會受這兩種類型備節點故障的影響.
當同步流複製的發生故障後,主節點終止連接到故障節點的walsender進程,potential狀態的備節點頂替這個故障的備節點,見下圖,與上述描述的故障對比,在potential替換故障節點的時候,在主節點上的查詢進程將暫停.因此,備節點的故障檢測是提高流複製高可用的一項重要功能.

 

在這個例子中,如果一個或者多個同步流複製備節點在運行中,主節點只和一個同步的備節點保持一致。

 

四.檢測備節點故障
流複製使用兩種常見的故障檢測程序,不需要任何特殊的硬件
1.備節點進程的故障檢測
當檢測到walsender和walreceiver的連接中斷時,主節點立即確定備節點或者walreceiver有故障,當低級別的網絡函數由於未能寫入和讀取walreceiver套接字藉口而返回錯誤時,主節點立即確定其失敗.
2.硬件或者網絡故障檢測
如果walreceiver在wal_sender_timeout內什麼都沒有返回,則主節點認爲備節點出現故障。與上述故障對比,即使備節點由於故障長時間沒有任何響應,也需要wal_sender_timeout這麼久的時間確認備節點故障.

根據故障類型,通常可以在故障和檢測之間會有時間差,特別是,在同步流複製中發生了一種類型的故障,主節點的所有事務處理將停止,直到探測到備節點故障,即使多個potential備節點在運行.

在9.2之前wal_sender_timeout參數是叫replication_timeout.

 

參考

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章