PostgreSQL/複製
複製是將資料更改從一個或多個數據庫(主庫)傳輸到一個或多個執行在其他節點上的其他資料庫(備庫)的過程。複製的目的是
- 高可用性:如果一個節點出現故障,另一個節點會代替它,應用程式可以持續工作。
- 擴充套件:工作負載需求可能對單個節點來說過高。因此,它被分散到多個節點。
PostgreSQL 提供了一系列在很大程度上相互獨立的概念,用於複製解決方案。它們可以根據用例進行選擇和組合,僅受少量限制。
事件
- 在基於觸發器的複製中,一個觸發器(每個表)啟動更改資料的傳輸。這種技術已經過時,不再使用。
- 在基於日誌的複製中,傳輸描述資料更改的資訊,這些資訊在 WAL 檔案中建立和儲存。
傳輸
- WAL 檔案傳輸複製(或基於檔案的複製)表示將完全填充的 WAL 檔案(16 MB)從主庫傳輸到備庫。這種技術不夠優雅,隨著時間的推移將被流式複製取代。
- 流式複製表示透過 TCP 連線將日誌記錄(單個更改資訊)從主庫傳輸到備庫。
主要引數:備用伺服器上的 recovery.conf 中的 'primary_conninfo'。
格式
- 在物理格式中,傳輸的 WAL 記錄與它們在 WAL 檔案中使用的結構相同。它們反映了資料庫檔案結構,包括塊號、VACUUM 資訊等等。
- 邏輯格式是對 WAL 記錄的解碼,解碼成一個抽象的格式,該格式獨立於 PostgreSQL 版本和硬體平臺。
主要引數:主伺服器上 postgres.conf 中的 'wal_level=logical'。
同步方式
- 在非同步複製中,資料被傳輸到不同的節點,而無需等待其接收確認。
- 在同步複製中,資料傳輸在 COMMIT 情況下會等待備用伺服器對其成功處理的確認。
主要引數:主伺服器上 postgres.conf 中的 'synchronous_standby_names'。
備用模式
- 熱備用:在熱備用模式下,備用伺服器在 'recovery 模式' 下執行,接受客戶端連線並處理它們的只讀查詢。
- 暖備用:在暖備用模式下,備用伺服器在 'recovery 模式' 下執行,不允許客戶端連線。
- 冷備用:雖然這不是官方的 PostgreSQL 術語,但冷備用模式可以與使用日誌傳輸技術的非執行備用伺服器相關聯。WAL 檔案被傳輸到備用伺服器,但不會在備用伺服器啟動之前進行處理。
主要引數:備用伺服器上 recovery.conf 中的 'hot_standby=on/off'。
架構
與上述類別不同,兩種不同的架構(主備和多主)並不嚴格區分。例如,如果你關注多主架構中的原子複製通道,你也會看到主備複製。
- 主備架構表示一個或多個備用節點從一個主節點接收更改資料的情況。在這種情況下,備用節點可能會將接收到的資料複製到其他節點,因此它們同時是主庫和備庫。
- 多主架構表示一個或多個備用節點從多個主節點接收更改資料的情況。
有 3 個主要的配置檔案
- 'postgres.conf'
- 'pg_hba.conf'
- 'recovery.conf'
'postgres.conf' 是主要的配置檔案。它用於配置主伺服器。備用伺服器上可能存在其他例項。
'pg_hba.conf' 是安全和身份驗證配置檔案。
recovery.conf 以前是可選的,包含恢復和恢復配置。從 PostgreSQL-12 開始,它不再使用,它的存在會阻止伺服器啟動。從 PostgreSQL-12 開始,recovery.conf 設定可以在 postgres.conf 中設定。
由於概念和相關配置值的眾多組合可能在開始時令人困惑,因此本書將重點關注一組最小的初始配置值。
WAL 檔案的生成是必要的,因為它們在崩潰後恢復時是必需的。如果它們被進一步用於將資訊傳輸到備用伺服器,則需要在檔案中新增更多資訊。這可以透過將 'replica' 或 'logical' 作為 wal_level 的值來啟用。
# WAL parameters on MASTER's postgres.conf wal_level=replica # 'archive' | 'hot_standby' in versions prior to PG 9.6 archive_mode=on # activate the feature archive_command='scp ...' # the transfer-to-standby command (or to an archive location, which is the original purpose of this command)
如果將傳輸技術從 WAL 檔案傳輸切換到流式傳輸,則不能停用 WAL 檔案生成和傳輸。出於安全原因,你可能仍然希望將 WAL 檔案傳輸到備用伺服器之外的其他平臺。因此,除了流式複製引數之外,你可以保留上述引數。
流式傳輸活動由備用伺服器啟動。當它在啟動時找到 'recovery.conf' 檔案時,它會假設需要執行恢復。在我們進行復制的情況下,它使用與從崩潰中恢復時幾乎相同的技術。'recovery.conf' 中的引數建議它在例項中啟動一個所謂的 WAL 接收器程序。該程序連線到主伺服器,並在那裡啟動一個 WAL 傳送器程序。這兩個程序在無休止的迴圈中交換資訊,而備用伺服器保持在 'recovery 模式' 下。
作業系統級別的授權應透過交換 SSH 金鑰來完成。
# Parameters in the STANDBY's recovery.conf
standby_mode=on # activates standby mode
# How to reach the master:
primary_conninfo='user=<replication_dbuser_at_master> host=<IP_of_master_server> port=<port_of_master_server>
sslmode=prefer sslcompression=1 krbsrvname=...'
# This file can be created by the pg_basebackup utility, see below
在主伺服器上,必須有一個具有特殊角色 REPLICATION 的特權資料庫使用者
CREATE ROLE <replication_dbuser_at_master> REPLICATION ...;
主伺服器必須通常接受來自備用伺服器的連線,並且允許一定數量的程序。
# Allow connections from standby to master in MASTER's postgres.conf listen_addresses ='<ip_of_standby_server>' # what IP address(es) to listen on max_wal_senders = 5 # no more replication processes/connections than this number
此外,必須能夠對複製資料庫使用者進行身份驗證。請注意,資料庫名稱的關鍵字 ALL 不包括複製活動的身份驗證。'Replication' 是一個獨立的關鍵字,必須明確指出。
# One additional line in MASTER's pg_hba.conf # Allow the <replication_dbuser> to connect from standby to master host replication <replication_dbuser> <IP_of_standby_server>/32 trust
現在你已經準備好開始。首先,你必須啟動主伺服器。其次,你必須將完整的資料庫從主伺服器傳輸到備用伺服器。最後,你可以啟動備用伺服器。與複製一樣,資料庫的傳輸也在備用伺服器上啟動。
pg_basebackup -h <IP_of_master_server> -D main --wal-methode=stream --checkpoint=fast -R
實用程式pg_basebackup 將所有內容傳輸到 'main' 目錄(應為空),在本例中它使用流式傳輸方法,它在主伺服器上啟動一個檢查點以強制執行資料庫檔案和 WAL 檔案的一致性,並且由於 -R 標誌,它生成之前提到的 recovery.conf 檔案。
從 PostgreSQL 9.4 版本開始,WAL 記錄從物理格式解碼到邏輯格式的功能被引入。物理格式包含 - 除其他外 - 塊號、VACUUM 資訊,並且取決於資料庫使用的字元編碼。相反,邏輯格式獨立於所有這些細節 - 從概念上來說,甚至獨立於 PostgreSQL 版本。解碼後的記錄被提供給註冊的流以供使用。
這種邏輯格式提供了一些巨大的優勢:傳輸到不同主要版本級別的資料庫、不同硬體架構,甚至傳輸到其他寫入主節點。因此,多主節點架構成為可能。此外,不需要複製整個叢集:你可以選擇單個數據庫物件。
在 9.5 版本中,此功能並未與核心 PostgreSQL 一起釋出。你需要安裝一些擴充套件。
CREATE EXTENTION btreee_gist; CREATE EXTENSION bdr;
由於該功能相對較新,我們不會提供詳細資訊,請參考 [文件](https://postgres.tw/docs/current/static/logicaldecoding.html)。還有一個重要的專案 [雙向複製](http://bdr-project.org/docs/stable/index.html) 基於此技術。
預設行為是非同步複製。這意味著,傳輸的資料在備用伺服器上進行處理,而不與主節點同步,即使在提交(COMMIT)的情況下也是如此。與這種行為相反,同步複製的主節點會在將提交(COMMIT)語句確認給其客戶端之前,等待備用節點成功處理這些語句。
同步複製透過引數 'synchronous_standby_names' 啟用。它的值標識那些需要同步的備用伺服器。'*' 表示所有備用伺服器。
# master's postgres.conf file synchronous_standby_names = '*'
只要備用伺服器正在執行,它就會持續處理傳入的更改資訊,並將這些資訊儲存在它的資料庫中。如果不需要處理來自應用程式的請求,它應該以暖備用模式執行。這種行為在 recovery.conf 檔案中強制執行。
# recovery.conf on standby server hot_standby = off
如果要允許客戶端連線,它必須以熱備用模式啟動。在這種模式下,允許客戶端進行只讀訪問 - 寫操作被拒絕。
# recovery.conf on standby server hot_standby = on
為了在主節點端生成足夠的資訊以供備用節點的熱備用模式使用,它的 WAL 級別也必須是 replica 或更高。
# postgres.conf on master server wal_level = replica
我們提供一些上述概念的典型組合,並展示它們的優缺點。
在這種情況下,主節點使用完全填充的 WAL 檔案(16 MB)將更改資料的相關資訊傳送給備用節點。備用節點持續處理傳入的資訊,這意味著在主節點上進行的更改會在一段時間後在備用節點上可見。
要構建這種場景,你需要執行與 [帶 PITR 的備份](/wiki/PostgreSQL/BackupAndRecovery#Physical_Backup_plus_PITR) 非常類似的步驟。
- 執行完全相同的物理備份,如 [帶 PITR 的備份](/wiki/PostgreSQL/BackupAndRecovery#Physical_Backup_plus_PITR) 中所述,並將備份傳輸到備用節點。
- 在主節點端,
postgres.conf必須指定wal_level=replica; archive_mode=on,以及一個用於將 WAL 檔案傳輸到備用節點端的 copy 命令。 - 在備用節點端,中心步驟是建立一個包含
standby_mode='on'行的recovery.conf檔案。這是備用節點在啟動後執行“無限恢復過程”的標誌。 recovery.conf必須包含一些其他的定義:restore_command, archive_cleanup_command
透過這種引數化,主節點將完全填充的 WAL 檔案複製到備用節點。備用節點透過將更改資訊複製到其資料庫檔案來處理接收到的 WAL 檔案。這種行為與崩潰後的恢復非常相似。不同之處在於,恢復模式在處理完最後一個 WAL 檔案後不會結束,備用節點會等待下一個 WAL 檔案的到來。
你可以將產生的 WAL 檔案複製到許多伺服器,並在每個伺服器上啟用暖備用。這樣做,你就可以獲得許多備用節點。
與暖備用場景相比,這種方案提供了一個非常有價值的功能:應用程式可以在備用節點以備用模式執行時連線到它併發送讀取請求。
為了實現這種情況,你需要在主節點端將 wal_level 增加到 hot_standby。這將在 WAL 檔案中新增一些額外的資訊。在備用節點端,你需要在 postgres.conf 中新增 hot_standby=on。啟動後,備用節點不僅會處理 WAL 檔案,還會接受和響應來自客戶端的讀取請求。
熱備用的主要用例是負載均衡。如果存在大量讀取請求,你可以透過將這些請求委託給一個或多個備用伺服器來減少主節點的負載。這種解決方案可以很好地擴充套件到大量並行工作的備用伺服器。
這兩個場景(冷/熱 + 日誌傳送)都有一個共同的缺點:傳輸資料的量始終為 16 MB。根據主節點上更改的頻率,啟動傳輸可能需要很長時間。下一章將介紹一種沒有此缺點的技術。
使用檔案將資訊從一臺伺服器傳輸到另一臺伺服器 - 如上述日誌傳送場景中所示 - 存在許多缺點,因此有點過時了。在執行在不同節點上的程式之間進行直接通訊更復雜,但提供了顯著的優勢:通訊速度快得多,在很多情況下,傳輸資料的量更小。為了獲得這些好處,PostgreSQL 實施了 流式複製技術,該技術透過 TCP 連線主節點和備用節點。這種技術添加了兩個額外的程序:主節點端的 WAL 傳送器 程序和備用節點端的 WAL 接收器 程序。它們交換有關主節點資料庫中資料更改的資訊。
通訊由備用節點啟動,必須使用具有 REPLICATION 許可權的資料庫使用者執行。該使用者必須在主節點端建立,並在主節點的 pg_hba.conf 檔案中授權。主節點必須總體上接受來自備用節點的連線,並接受一定數量的程序。作業系統級別的授權應該透過交換 SSH 金鑰來完成。
Master site:
============
-- SQL
CREATE ROLE <replication_dbuser_at_master> REPLICATION ...;
# postgresql.conf: allow connections from standby to master
listen_addresses ='<ip_of_standby_server>' # what IP address(es) to listen on
max_wal_senders = 5 # no more replication processes/connections than this number
# make hot standby possible
wal_level = replica # 'hot_standby' in versions prior to PG 9.6
# pg_hba.conf: one additional line (the 'all' entry doesn't apply to replication)
# Allow the <replication_dbuser> to connect from standby to master
host replication <replication_dbuser> <IP_of_standby_server>/32 trust
Standby site:
=============
# recovery.conf (this file can be created by the pg_basebackup utility, see below)
standby_mode=on # activates standby mode
# How to reach the master:
primary_conninfo='user=<replication_dbuser_at_master_server> host=<IP_of_master_server> port=<port_of_master_server>
sslmode=prefer sslcompression=1 krbsrvname=...'
# postgres.conf: activate hot standby
hot_standby = on
現在你已經準備好了。首先,你需要啟動主節點。其次,你需要將主節點的完整資料庫傳輸到備用節點。最後,你啟動備用節點。與複製活動一樣,資料庫的傳輸也是由備用節點啟動的。
pg_basebackup -h <IP_of_master_server> -D main --wal-method=stream --checkpoint=fast -R
實用程式 pg_basebackup 將所有內容傳輸到 'main' 目錄(應該是空的),在這種情況下,它使用流式方法,它在主節點端啟動一個檢查點以強制執行資料庫檔案和 WAL 檔案的一致性,並且由於 -R 標誌,它會生成前面提到的 recovery.conf 檔案。
啟用“熱”備用與之前的用例完全相同。
如果你需要管理複雜的複製用例,你可能想檢視開源專案 [repmgr](https://repmgr.org/)。它可以幫助你監控節點叢集或執行故障轉移。