標籤:
到目前為止,我們已經處理了基於檔案的複製(或記錄傳送)和簡單的基於流複製的設定。在兩種情況中,在master上事務被提交之後,資料被提交,由slave接收。在master提交和slave實際上完全地接收到資料這段時間,它仍然會丟失。
在本章中,我們將學習如下主題:
• 確保沒有任何事務丟失
• 配置PostgreSQL同步複製
• 理解並使用application_name
• 同步複製的效能影響
• 複製的速度最佳化
5.1 設定同步複製
正如前面提到的,同步複製已經被用來盡一切花費來保護您資料。同步複製的核心思想是在master給用戶端返回成功之前,事務必須至少存在於兩個伺服器之上。設定同步複製工作就像設定非同步複製。只是極少數在本章討論的參數必須被改變來享受同步複製的祝福。但是,如果您想要在同步複製的基礎上建立您自己的設定,我們建議從非同步設定開始,並逐步擴充您的配置來把它變成同步複製。這將允許您更容易地調試系統,並且可以避免這個過程中的好多問題。
5.1.1 理解同步複製的缺點
您必須要瞭解的關於同步複製的最重要的事情是它是相當昂貴的。您還記得第一章的關於CAP的理論,關於光速,等等?同步複製和它的缺點是為什麼我們決定將所有這些背景資訊包含在這本書中的核心原因之一。理解同步複製的物理限制是必要的,否則您可能最終身陷困境。
當設定同步複製時,盡量記住以下幾點:
• 最小化延遲
• 確保您有冗餘延遲
• 同步複製比非同步複製代價更高
5.1.2 理解application_name參數
application_name 在同步設定中承擔著一個重要角色。在典型的應用中,人們處於調試的目的使用application_name 參數。它可以協助您追蹤bug,確定一個應用程式在做什麼,等等:
test=# SHOW application_name;
application_name
------------------
psql
(1 row)
test=# SET application_name TO ‘whatever‘;
SET
test=# SHOW application_name;
application_name
------------------
whatever
(1 row)
正如您所看到的,自由地設定application_name參數是可能的。這個設定對於我們所在的這個會話是可用的,只要我們一中斷連線就會消失。現在的問題是:在同步複製中application_name必須做什嗎?
接下來,故事是這樣的:如果slave通過流串連到master,它發送一個application_name 作為 primary_conninfo 設定的一部分。如果這個application_name 正好是 synchronous_standby_names 的第一個條目,slave將成為一個同步伺服器。
[在級聯複製情況下(這意味著一個slave再一次被串連到一個slave),級聯的slave不會再被同步地看待。]
請記住所有這些資訊,我們可以繼續向前走,並配置我們的第一個同步複製。
5.1.3 使得同步複製工作
為了給您顯示同步複製是如果工作的,本章將包括一個完全的工作例子,列出所有相關的配置參數。
必須在master上做幾個改變。master上的postgresql.conf檔案將需要如下設定:
wal_level = hot_standby
max_wal_senders = 5 # or any number
synchronous_standby_names = ‘book_sample‘
hot_standby = on
# on the slave to make it
然後,我們必須配置pg_hba.conf正如我們已經在前面章節說看到的。之後,伺服器可以重新啟動,master準備行動。
[我們建議也設定wal_keep_segments來在master資料庫上保持更多的交易記錄。這使得整個設定更加健壯。]
下一步,我們可以執行一個基礎備份,正如我們之前已經做過的。我們必須在slave上調用pg_basebackup。理論上,做基礎備份的時候(--xlog-method=stream)我們已經包括了交易記錄。這允許我們快速地啟動伺服器,並且沒有任何較大的風險。
[--xlog-method=stream 和 wal_keep_segments 是一個很好的組合,並且在大多數情況下,在我們看來,是設定完美並安全地工作的系統的保證。]
我們已經建議在master上設定hot_standby;config檔案無論如何都會被複製,因此,您可以省一步到postgresql.conf中更改此設定。當然,這不是藝術,而是一種方便,實用的方法。
一旦基礎備份完成。我們就可以向前邁進,寫一個簡單的recovery.conf檔案適用於同步複製。
iMac:slavehs$ cat recovery.conf
primary_conninfo = ‘host=localhost
application_name=book_sample
port=5432‘
standby_mode = on
config檔案看起來和以前的一樣。唯一不同的是,我們已經添加了application_name。注意application_name參數必須和master上synchronous_standby_names的設定一樣。
一旦我們寫完了recovery.conf,我們就可以啟動slave了。在我們的例子中,slave和master在同一台伺服器上。在這種情況下,您必須確保這兩個執行個體採用不同的TCP連接埠。否則第二個啟動的執行個體將不能啟動。連接埠可以很容易地在postgresql.conf中改變。
完成這些步驟之後,資料庫執行個體就可以啟動了。slave將檢查它的串連資訊並串連到master。一旦它重放所有相關的交易記錄,它將處於同步狀態;master和slave從那時起將保持完全相同的資料。
5.1.4 檢查複製
現在我們已經啟動的資料庫執行個體,我們可以串連到系統看看系統是否正常地工作。
要檢查複製,我們可以串連到master看一看pg_stat_replication。對於這個檢查,我們可以串連到我們(master)執行個體任何資料庫內部。
postgres=# \x
Expanded display is on.
postgres=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 62871
usesysid | 10
usename | hs
application_name | book_sample
client_addr | ::1
client_hostname |
client_port | 59235
backend_start | 2013-03-29 14:53:52.352741+01
state | streaming
sent_location | 0/30001E8
write_location | 0/30001E8
flush_location | 0/30001E8
replay_location | 0/30001E8
sync_priority | 1
sync_state | sync
這個系統檢視表將為每個串連到您的master系統的slave顯示一行。
[\x會讓輸出對你來說更可讀。如果您不使用\x來變換輸出,這些行會很長,對您來說理解這個表的內容會相當困難。在擴充顯示模式中,每一列將成為一行。]
您可以看到,application_name參數已經被從slave(在我們的例子中book_sample)從連接字串傳遞給了master。由於application_name參數與master的synchronous_standby_names設定相匹配,我們已經使系統同步地複製了;不會再有任何事務會丟失,因為每個事務都將會瞬間存在於兩個伺服器上。sync_state設定會告訴您資料是如何從master移動到slave上的。
[您也可以在synchronous_standby_names中使用一系列application_names或只是一個*以指示第一個slave必須是同步的。]
5.1.5 理解效能問題
在本書中的不同觀點中我們已經能夠指出,同步複製是一件昂貴的事情。請記住,我們必須等待一台遠端的伺服器,不僅僅是本地的系統;這兩個節點之間的網路需要加速。寫入到不只一個節點總是比唯寫入一個節點更昂貴。因此,我們一定要盯緊速度,否則您可能會面臨一些討厭的意外。
[想一下我們在本書中前面的CAP理論學到了什麼;帶有嚴重的物理限制的同步複製對效能造成的影響是相當明顯的。]
您真的需要問您自己的主要的問題是:您真的希望同步地複製所有的事務嗎?在很多情況下,您不需要。為了證明我們的觀點,讓我們想象一個典型的情境:一家銀行想要儲存會計相關的資料以及一些日誌資料。我們絕不會希望因為資料庫節點出現故障而失去幾百萬。這種資料庫可能是值得的,我們可以同步地複製它。然而,日誌資料是完全不同的。它太昂貴而不能用同步複製來應對。所以,我們想以非同步方式複製這些資料來確保最大的輸送量。
我們該如何配置一個系統,以處理重要的以及不重要的事務?答案就在您在本書的前面已經看到的一個變數上:synchronous_commit變數。
5.1.6 設定synchronous_commit 為 on
在預設的PostgreSQL配置中,synchronous_commit已經被設定為on。
在這種情況下,提交將會等待直到當前同步的standby表明它已經收到事務的提交記錄並把它重新整理到磁碟。換句話說,兩台伺服器必須報告資料已經安全地寫入。除非兩台伺服器同時崩潰,您的資料將免於潛在的問題。(兩台伺服器同時崩潰是不可能)。
設定synchronous_commit為 remote_write
重新整理到兩個磁碟是非常昂貴的。在許多情況下,知道遠程伺服器已經接收了XLOG並把它傳遞到slave的作業系統而不重新整理到磁碟已經足夠了,正如我們以可以肯定的是,我們不會同時失去兩台伺服器,這是在效能和一致性資料保護之間的一個合理的折中。
設定synchronous_commit 為off
在前面的章節中我們已經處理過這個設定。這個想法是延遲WAL寫,以減少磁碟排清。如果效能比耐久性重要,它可以被使用。在複製的情況下,這意味著我們沒有以一種完全同步的方法來執行複製。
請記住,這可能對您的應用產生嚴重的影響。想象 master 上的事務提交和您想要立即查詢在 slave 上的資料。在您實際得到到期的資料期間仍然還有一個小視窗。
設定 synchronous_commit 為 local
local 將會本地重新整理而不會等待覆制的回應。換句話說,它將把您的事務轉換為非同步事務。把synchronous_commit設定為local,會引起一個時間視窗,在這個視窗期間slave會返回稍顯陳舊的資料。 當您決定卸載讀取的slave時,您應該記住這一現象。簡而言之,如果您想同步地複製,您必須確保synchronous_commit 要麼設定為 on 或設定為 remote_write。
在系統運行時更改耐久性設定
在系統運行時更改資料複製的方式是很容易的。在本章中,我們已經通過調整synchronous_standby_names (master)和application_name (slave)參數
建立了一個完全同步的複製基礎架構。PostgreSQL的好處是,您可以在系統運行時改變您耐久性要求:
test=# BEGIN;
BEGIN
test=# CREATE TABLE t_test (id int4);
CREATE TABLE
test=# SET synchronous_commit TO local;
SET
test=# \x
Expanded display is on.
test=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid | 62871
usesysid | 10
usename | hs
application_name | book_sample
client_addr | ::1
client_hostname |
client_port | 59235
backend_start | 2013-03-29 14:53:52.352741+01
state | streaming
sent_location | 0/3026258
write_location | 0/3026258
flush_location | 0/3026258
replay_location | 0/3026258
sync_priority | 1
sync_state | sync
test=# COMMIT;
COMMIT
在這個例子當中,我們已經在系統啟動並執行過程中改變了系統的耐久性。它將確保這個特殊的事務不會等待slave重新整理磁碟。注意,正如您所見,sync_state沒有改變。不要被您在這裡看到東西愚弄;您可以完全依靠本節所述的行為。PostgreSQL完全能夠單獨處理每一個事務。這是這個奇妙的開來源資料庫獨特的特徵;它使您可以控制並讓您決定使用哪一種耐久性要求。
PostgreSQL Replication之第五章 設定同步複製(1)