PostgreSQL流復制之一:原理+環境搭建(轉發+整理)


資料來源:

原理:https://blog.51cto.com/wn2100/2238996

原理:https://www.cnblogs.com/ilifeilong/p/7002687.html

主備庫配置:https://blog.csdn.net/silenceray/article/details/54692908

postgres主備切換之文件觸發方式:https://blog.csdn.net/m15217321304/article/details/88850146

參考:流復制延遲參數https://cloud.tencent.com/developer/article/1524114

 

一、PostgreSQL通過WAL日志構建高可靠性原理:

PostgrepSQL在數據目錄的子目錄pg_xlog子目錄中維護了一個WAL日志文件,可以把WAL日志備份到另外一台備份服務器,通過重做WAL日志的方式在備服務器上恢復數據(類似Oracle的redo日志)。

WAL日志復制到另外一台備份服務器可以有兩種方式:

1、 WAL日志文件復制

此種方式是寫完一個WAL日志后,才把WAL日志文件拷貝到備份數據庫中。這樣通常備份會落后主庫一個WAL日志文件,當主數據庫發生故障時,主數據庫的WAL文件並沒有填充完畢未傳輸(默認16MB)、或者時延等原因導致WAL文件沒有傳輸完畢,會導致被數據庫可能存在一定的數據丟失。此種方式是postgreSQL9.0前版本主要提供的WAL日志復制機制。

采用此方式的WAL復制,需要:

  • 主數據庫的wal_level配置為archive或以上。
  • PostgreSQL 9.1之后提供了一個很方便的工具pg_basebackup,使用完成一次基礎備份到備數據庫。
  • 后續產生WAL文件,可以通過archive_command參數調度命令傳輸至備機。

2、流復制(Streaming Replication)

流復制是PostgreSQL 9.0之后才提供的新的傳遞WAL日志的方法。通過流復制,備庫不斷的從主庫同步相應的數據,並在備庫apply每個WAL record,這里的流復制每次傳輸單位是WAL日志的record。它的好處是只要主庫一產生日志,就會馬上傳遞到備庫,同WAL日志文件相比有更低同步延遲。

同時PostgreSQL9.0之后提供了Hot Standby能力,備庫在應用WAL record的同時也能夠提供只讀服務。

PostgreSQL的流復制最多支持1主8備、支持級聯復制(主->備1,備1->備2)。

 

PostgreSQL流復制的核心部分由walsender,walreceiver和startup三個進程組成:

  1. walreceiver啟動后通過recovery.conf文件中的primary_conninfo參數信息連向主庫,主庫通過連接參數replication=true啟動walsender進程。
  2. walreceiver執行identify_system命令,獲取主庫systemid/timeline/xlogpos等信息,執行TIMELINE_HISTORY命令拉取history文件。
  3. 執行wal_startstreaming開始啟動流復制,通過walrcv_receive獲取WAL日志,期間也會回應主庫發過來的心跳信息(接收位點、flush位點、apply位點),向主庫發送feedback信息(最老的事務id),避免vacuum刪掉備庫正在使用的記錄。
  4. 執行walrcv_endstreaming結束流復制,等待startup進程更新receiveStart和receiveStartTLI,一旦更新,重新進入2/3/4步驟。

 WAL流復制支持同步、異步方式:

  •  異步流復制模式中,主庫提交的事務不會等待備庫接收WAL日志流並返回確認信息,因此異步流復制模式下主庫與備庫的數據版本上會存在一定的處理延遲,延遲的時間主要受主庫壓力、備庫主機性能、網絡帶寬等影響,當正常情況下,主備的延遲通常在毫秒級的范圍內,當主庫宕機,這個延遲就主要受到故障發現與切換時間的影響而拉長,不過雖然如此,這些數據延遲的問題,可以從架構或相關自動化運維手段不斷優化設置。
  • 同步流復制模式中,要求主庫把WAL日志寫入磁盤,同時等待WAL日志記錄復制到備庫、並且WAL日志記錄在任何一個備庫寫入磁盤后,才能向應用返回Commit結果。一旦所有備庫故障,在主庫的應用操作則會被掛起,所以此方式建議起碼是1主2備。

 

二、搭建PostgreSQL數據庫異步流復制環境

前提,數據庫安裝完畢。以主、備庫如下規划為例:

主庫地址/端口

10.10.10.1  /  5432

備庫地址/端口

10.10.10.2  /  5432

備主流復制用戶名/密碼

u_standby  /  standby123

數據庫用戶名

postgre

PostgreSQL主備數據庫的同步設置主要涉及如下文件:

  1. pg_hba.conf                 postgresql 主庫訪問規則文件
  2. postgresql.conf            postgresql 主庫配置文件
  3. recovery.conf               postgresql 備庫訪問主庫配置文件
  4. .pgpass                        postgresql 備庫訪問主庫的密碼文件

正常主備流復制情況下:

  • 主庫需要pg_hba.conf、postgresql.conf
  • 備庫需要recovery.conf、.pgpass

實際操作中,建議主、備庫上都配置這四個文件,因為主、備庫角色是隨着倒換變更的。注:recovery.conf文件在備庫上是recovery.conf,在主庫上配置為recovery.done。

 

主庫配置:

1、   配置postgresql.conf

wal_level = hot_standby  # minimal, replica, or logical   使得日志支持Streaming Replication

max_wal_senders = 2  # max number of walsender processes   這個設置了可以最多有幾個流復制連接,幾個並發的standby數據庫就設置幾個

wal_keep_segments = 256     設置流復制保留的最多的xlog數目,不要設置太小導致WAL日志還沒有來得及傳送到standby就被覆蓋。一個WAL文件默認16M

hot_standby = on  # "on" allows queries during recovery  設置為備庫時是否支持可讀

logging_collector = on

log_directory = 'pg_log'

log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'

 

2、   配置pg_hba.conf

# TYPE  DATABASE    USER            ADDRESS              METHOD

host    all             all             127.0.0.1/32            trust

host    all             all             ::1/128                trust

host    replication      u_standby        10.10.10.0/32       trust

其中:

1) u_standby為在主庫上創建的用於備庫連接主庫進行流復制的用戶,此用戶需要用戶需要有REPLICATION權限和LOGIN權限。開戶如:

create user u_standby SUPERUSER LOGIN password 'standby123';

2) 10.10.10.0/32為備庫地址段+掩碼;也可配置為具體的standby數據庫地址+掩碼,可配置多條。用於指定哪些地址的standby數據用哪個用戶名/密碼到主庫獲取WAL日志數據。使用地址段格式,則地址段內的IP都可以無密碼對此數據庫進行訪問,安全性可能會降低。因此,在生產環境中建議嚴格按照具體主機IP方式配置。

 

3、   (可選)配置recovery.done、.pgpass

同備庫recovery.conf、.pgpass配置。recovery.conf中如下IP、端口、用戶名要對應備庫信息:

primary_conninfo = 'host=10.10.10.1 port=5432 user=u_standby'   備庫連接主庫地址、端口、用戶名、密碼

 

4、   配置完畢需重啟數據庫

pg_ctl restart -m fast

 

進行主庫->備庫基礎備份:

1、   關閉備庫,並清空數據

  $pg_ctl stop -m fast

  rm -rf /var/lib/pgsql/data/*

 2、   進行一次主庫數據基本備份到備庫

方式一(在主庫操作):

  //開啟備份功能,pg_start_backup() 函數會在主庫上發起一個在線備份,命令執行后,將數據文件壓縮拷貝到備份節點上:

  $postgres=# select pg_start_backup('backup0001')

  //將data目錄下的數據遠程拷貝到備庫的data目錄下

  $scp -r /opt/pgsql/data/* 10.10.10.2:/opt/pgsql/data/

  //關閉備份功能

  $postgres=# select pg_stop_backup()

方式二(9.0版本后引入了pg_basebackup工具,在備庫操作):

  pg_basebackup工具支持對主庫發起一個基准備份,發起備份需要超級用戶權限或REPLICATION權限,注意max_wal_senders參數配置,因為pg_basebackup工具將消耗至少一個WAL發送進程。

  //如下IP為主庫地址

  pg_basebackup -h 10.10.10.1 -U u_standby -F p -x -P -R -D /var/lib/pgsql/9.5/data/ -1 rep_backup   //-R 表示會在備份結束后自動生成recovery.conf文件,這樣就避免了手動創建。

 

備庫配置:

1、   修改postgresql.conf

  hot_standby = on  # "on" allows queries during recovery  設置為備庫時是否支持可讀

2、   配置recovery.conf

  standby_mode = on

  recovery_target_timeline = 'latest'

  primary_conninfo = 'host=10.10.10.1 port=5432 user= u_standby password=standby123 '   本庫為備庫會,連接主庫地址、端口、用戶名、密碼

3、   設置連接主庫密碼.pgpass

  10.10.10.1: 5432:replication: u_standby:standby123  //備庫都主庫同步WAL日志使用

  10.10.10.2: 5432:replication: u_standby:standby123  //倒換后,主庫降備庫,新備庫使用

4、   配置完畢需重啟數據庫

  pg_ctl start

 

結果檢查:

1、   配置成功后,可以查看主、備庫的walsender、walreceiver進程。

ps -ef | grep wal

主庫:

postgres 6939 6935 0 23:16 ? 00:00:00 postgres: wal writer process

postgres 6983 6935 0 23:42 ? 00:00:00 postgres: wal sender process repuser 172.17.0.5(45910) streaming 0/3000140

備庫:

postgres 26481 26479 0 23:42 ? 00:00:00 postgres: wal receiver process streaming 0/3000140

 

三、PostgreSQL的同步流復制

同步流復制配置內容類似異步流復制,差異點在於:

1、   主庫的postgresql.conf文件,增加:

  synchronous_standby_names = 'standby001'

       synchronous_standby_names是設置同步流復制的備庫的主機名,該名稱會在備庫中的參數中指定。

2、   備庫的recoveryt.conf文件

  primary_conninfo = 'host=192.168.100.32 port=5866 user=tbing application_name=standby001'

       application_name參數就是設置的同步流復制備庫的主機名,該參數值和主庫的synchronous_standby_names的參數值一致。

3、   檢查流復制狀態

  執行:

  select * from pg_stat_replication

  返回:

  sync_state       | sync     表示同步流復制

  sync_state       | async    表示異步流復制

 

四、PostgreSQL主備數據庫切換

1、識別當前庫主、備角色:

方式一:

  postgres=# select pg_is_in_recovery();   結果是f則為主庫,t為備庫

方式二:

  pg_controldata 結果為cluster state是in production則為主庫;結果為cluster state是in archive recovery則為備庫

方式三:

  Select pid, application_name, client_addr, client_port, state, sync_state from pg_stat_replication  查詢到結果為主庫,查詢不到結果為備庫。

 

2、主備倒換

在PostgreSQL如主庫出現異常時,備庫如何激活。有2種方式:

方式一:使用pg_ctl promote來激活(PostgreSQL9.1后支持)

(1)關閉主庫(模擬主庫故障):

  $ pg_ctl stop -m fast

(2)在備庫上執行pg_ctl promote命令激活備庫

  如果recovery.conf變成recovery.done表示備庫已切換成主庫

(3)原主庫變備庫

  在新備庫上創建recovery.conf、.pgpass文件,內容參考前文章節。啟動新備庫:

  $ pg_ctl start

方式二:備庫在recovery.conf文件中有個配置項trigger_file,是激活standby的觸發文件,通過檢測這個文件是否存在,存在則激活standby為master。

(1)在recovery.conf中配置觸發器文件地址,修改本參數后需要重啟備庫:

  recovery_target_timeline = 'latest'

  standby_mode = on

  primary_conninfo = 'host=10.10.10.1 port=5432 user= u_standby password=standby123 '

  trigger_file = '/home/postgres/pg11/trigger'

(2)停掉原主庫,會發現原備庫變為可讀寫。

  $ pg_ctl stop -m fast

(3)在備庫創建trigger_file

  $ touch /home/postgres/pg11/trigger

(4)發現原備庫變為主庫,方法參考“識別當前庫主、備角色”。

 

3、故障的原主庫,重新作為備庫使用

在異步流復制(async)模式下,主庫故障切換后,可能存在原主庫故障時還有數據沒來及的復制到備庫,這些數據將丟失。(注:PostgreSQL的Streaming Replication是以事務為單位,即使數據未同步完畢,也不會出現備庫某個事務只恢復一半的情況,因此事務一致性還是可以保證的。)

此種情況下,原主庫的最后一個事務時間戳比復制到原備庫(新主庫)的事務時間戳更新。比如:倒換前最后幾個事務是100/101/102,故障前流復制到100事務,則故障切換后,原主庫中最新一個事務是102,原備庫(新主庫)中復制的最后一個事務是100,后續新主庫(原備庫)將在100的基礎上,進行新的事務操作。原主庫數據、新主庫數據出現分叉點。因此,如果希望原主庫恢復服務后作為新備庫運行,則需要:

方式一:刪庫,重搭新備庫(詳細參考前文備庫配置過程)

  1、 關閉庫,並清空數據(清楚數據即可,不需要重裝數據庫)

    pg_ctl stop -m fast

    rm -rf /var/lib/pgsql/data/*

  2、 新備庫進行數據基本備份

    pg_basebackup  ….

  3、 啟動新備庫

    pg_ctl start

方式二:采用pg_rewind降級為備庫,繼續服務

如果你的數據庫到達TB級別,采用方式一的全量數據基礎備份將花費數個小時。為了解決此問題,PostgreSQL9.5引入了pg_rewind功能。原主庫(新備庫)可以通過pg_rewind操作實現故障時間線的回退。回退后再從新主庫中獲取最新的后續數據。此時,原主庫的數據無須進行重新全量初始化就可以繼續進行Streaming Replication,並作為新的Slave使用。

詳見pg_rewind使用說明。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM