連續(xù)歸檔可以用來創(chuàng)建一個(gè)高可用(HA)集群配置, 其中有一個(gè)或多個(gè)后備服務(wù)器隨時(shí)準(zhǔn)備在主服務(wù)器失效時(shí)接管操作笤休。 這種能力被廣泛地稱為溫備或日志傳送示绊。
主服務(wù)器和后備服務(wù)器一起工作來提供這種能力惶看,但這些服務(wù)器只是松散地組織在一起。主服務(wù)器在連續(xù)歸檔模式下操作裂明, 而每一個(gè)后備服務(wù)器在連續(xù)恢復(fù)模式下操作并且從主服務(wù)器讀取WAL文件椿浓。 要啟用這種能力不需要對(duì)數(shù)據(jù)庫表做任何改動(dòng), 因此它相對(duì)于其他復(fù)制方案降低了管理開銷闽晦。 這種配置對(duì)主服務(wù)器的性能影響也相對(duì)較低轰绵。
直接從一個(gè)數(shù)據(jù)庫服務(wù)器移動(dòng)WAL記錄到另一臺(tái)服務(wù)器通常被描述為日志傳送。? PostgreSQL通過一次一文件(WAL段) 的WAL記錄傳輸實(shí)現(xiàn)了基于文件的日志傳送尼荆。不管 WAL 文件(16 MB)被送到一個(gè)臨近的系統(tǒng)左腔、同一站點(diǎn)的另一個(gè)系統(tǒng)或是在地球遙遠(yuǎn)的另一端的一個(gè)系統(tǒng)上,它都可以在任何距離上被簡單和便宜地傳送捅儒。這種技術(shù)所需的帶寬取根據(jù)主服務(wù)器的事務(wù)率而變化液样。基于記錄的日志傳送具有更細(xì)的粒度并且能夠在網(wǎng)絡(luò)連接上以流的方式增量傳遞WAL的改變巧还。
需要注意的是日志傳送是異步的鞭莽,即WAL記錄是在事務(wù)提交后才被傳送。 正因?yàn)槿绱唆锏唬谝粋€(gè)窗口期內(nèi)如果主服務(wù)器發(fā)生災(zāi)難性的失效則會(huì)導(dǎo)致數(shù)據(jù)丟失澎怒, 還沒有被傳送的事務(wù)將會(huì)被丟失。 基于文件的日志傳送中這個(gè)數(shù)據(jù)丟失窗口的尺寸可以通過使用參數(shù) archive_timeout進(jìn)行限制阶牍,它可以被設(shè)置成低至數(shù)秒喷面。 但是這樣低的設(shè)置大體上會(huì)增加文件傳送所需的帶寬星瘾。 流復(fù)制允許更小的數(shù)據(jù)丟失窗口。
這種配置的恢復(fù)性能是足夠好的惧辈,后備服務(wù)器在被激活后通常只有片刻就可以達(dá)到完全可用琳状。 因此,這被稱為一種提供高可用性的溫備配置盒齿。 從一個(gè)已歸檔的基礎(chǔ)備份恢復(fù)一個(gè)服務(wù)器并且前滾將需要較長時(shí)間念逞, 因此該技術(shù)只提供了災(zāi)難恢復(fù)的一種方案,而不適合于高可用性边翁。
如果一臺(tái)后備服務(wù)器只有被提升為一臺(tái)主控服務(wù)器后才能被連接翎承, 它被稱為一臺(tái)溫后備服務(wù)器, 而一臺(tái)能夠接受連接并且提供只讀查詢的后備服務(wù)器被稱為一臺(tái) 熱后備服務(wù)器符匾。
規(guī)劃設(shè)計(jì)
創(chuàng)建主服務(wù)器和后備服務(wù)器通常是明智的审洞,因此它們可以盡可能相似, 至少從數(shù)據(jù)庫服務(wù)器的角度來看是這樣待讳。特別地芒澜, 與表空間相關(guān)的路徑名將被未經(jīng)修改地傳遞,因此如果該特性被使用创淡, 主痴晦、備服務(wù)器必須對(duì)表空間具有完全相同的掛載路徑。 記住如果CREATE TABLESPACE在主服務(wù)器上被執(zhí)行琳彩, 在命令被執(zhí)行前誊酌,它所需要的任何新掛載點(diǎn)必須在主服務(wù)器和所有后備服務(wù)器上先創(chuàng)建好。在任何情況下硬件架構(gòu)必須相同露乏,從一個(gè) 32 位系統(tǒng)傳送到一個(gè) 64 位系統(tǒng)將不會(huì)工作碧浊。
通常,不能在兩個(gè)運(yùn)行著不同主版本PostgreSQL的服務(wù)器之間傳送日志瘟仿。PostgreSQL 全球開發(fā)組的策略是不在次版本升級(jí)中改變磁盤格式箱锐, 因此在主服務(wù)器和后備服務(wù)器上運(yùn)行不同次版本將會(huì)成功地工作。不過劳较, 在這方面并沒有提供正式的支持驹止,因此我們建議讓主備服務(wù)器上運(yùn)行的版本盡可能相同。 當(dāng)升級(jí)到一個(gè)新的次版本時(shí)观蜗,最安全的策略是先升級(jí)后備服務(wù)器 — 一個(gè)新的次版本發(fā)行更可能兼容從前一個(gè)次版本讀取 WAL 文件臊恋。
后備服務(wù)器操作(restore_command)
在后備模式中,服務(wù)器持續(xù)地應(yīng)用從主控服務(wù)器接收到的 WAL墓捻。 后備服務(wù)器可以從一個(gè) WAL 歸檔(restore_command) 或者通過一個(gè) TCP 連接直接從主控機(jī)(流復(fù)制)讀取 WAL抖仅。 后備服務(wù)器也會(huì)嘗試恢復(fù)在后備集簇的pg_wal目錄中找到的 WAL。 通常在一次數(shù)據(jù)庫重啟后,后備機(jī)將重播在重啟之前從主控機(jī)流過來的 WAL撤卢, 但是你也可以在任何時(shí)候手動(dòng)拷貝文件到pg_wal讓它們被重播环凿。
在啟動(dòng)時(shí),后備機(jī)通過恢復(fù)歸檔位置所有可用的WAL開始凸丸, 稱為restore_command拷邢。
1) 一旦重播到達(dá)可用WAL的末尾并且 restore_command失敗袱院,它會(huì)嘗試恢復(fù)pg_wal 目錄中可用的任何WAL屎慢。
2) 如果嘗試重試恢復(fù)失敗且流復(fù)制已被配置, 后備機(jī)會(huì)嘗試連接到主服務(wù)器并從在歸檔或pg_wal 中找到的最后一個(gè)可用記錄開始流式傳送 WAL忽洛。
3) 如果嘗試重試恢復(fù)失敗且沒有配置流復(fù)制腻惠, 或者該連接后斷開,后備機(jī)返回到步驟 1) 且嘗試再次從歸檔里的文件恢復(fù)欲虚。
這種嘗試歸檔集灌、pg_wal和流復(fù)制的循環(huán)會(huì)一直重復(fù)直到服務(wù)器停止或者一個(gè)觸發(fā)器文件觸發(fā)了故障轉(zhuǎn)移。
當(dāng)pg_ctl promote(升主)被運(yùn)行或一個(gè)觸發(fā)器文件被找到 (trigger_file),后備模式會(huì)退出并且服務(wù)器會(huì)切換到普通操作。 在故障轉(zhuǎn)移前橘忱,在歸檔或pg_wal中可用的任何WAL將立即被恢復(fù)噩凹, 但不會(huì)嘗試連接到主控機(jī)。
為后備服務(wù)器準(zhǔn)備主控機(jī)
在主服務(wù)器上設(shè)置連續(xù)歸檔到一個(gè)后備服務(wù)器可訪問的歸檔目錄显沈。 如果主服務(wù)器垮掉該歸檔位置應(yīng)當(dāng)是后備服務(wù)器可訪問的,可以位于后備服務(wù)器本身或者另一個(gè)可信賴的服務(wù)器,而不是位于主控服務(wù)器上驯鳖。
如果使用流復(fù)制,在主服務(wù)器上設(shè)置認(rèn)證來允許來自后備服務(wù)器的復(fù)制連接久免。創(chuàng)建一個(gè)角色并且在pg_hba.conf中提供一個(gè)或多個(gè)數(shù)據(jù)庫域被設(shè)置為replication的項(xiàng)浅辙,還要保證在主服務(wù)器配置文件中max_wal_senders設(shè)置足夠大的值。如果使用復(fù)制槽阎姥, 請(qǐng)確保max_replication_slots設(shè)置得足夠高记舆。
建立一個(gè)后備服務(wù)器
要建立后備服務(wù)器,恢復(fù)從主服務(wù)器取得的基礎(chǔ)備份呼巴。 在后備服務(wù)器的集簇?cái)?shù)據(jù)目錄中創(chuàng)建一個(gè)恢復(fù)命令文件recovery.conf氨淌, 并且打開standby_mode。將restore_command 設(shè)置為從WAL歸檔中復(fù)制文件的簡單命令伊磺。
如果為了高可用性而建立多個(gè)后備服務(wù)器盛正, 將recovery_target_timeline設(shè)置為latest,使該后備服務(wù)器遵循發(fā)生在故障轉(zhuǎn)移到另一個(gè)后備服務(wù)器之后發(fā)生的時(shí)間線改變屑埋。
注意:不要把pg_standby或相似的工具和這里描述的內(nèi)建后備模式一起使用豪筝。 如果文件不存在,restore_command應(yīng)該立即返回失敗,該服務(wù)器將再次嘗試該命令续崖。
如果使用流復(fù)制敲街,在primary_conninfo中填入一個(gè)libpq連接字符串,其中包括主機(jī)名(或IP地址)和連接到主服務(wù)器所需的任何附加細(xì)節(jié)(包括認(rèn)證口令)严望。
如果為高性能而建立后備服務(wù)器多艇,像主服務(wù)器一樣建立WAL歸檔、 連接和認(rèn)證像吻,因?yàn)樵诠收限D(zhuǎn)移后該后備服務(wù)器將作為一個(gè)主服務(wù)器工作峻黍。
如果使用一個(gè)WAL歸檔,可以使用archive_cleanup_command 參數(shù)來移除后備服務(wù)器不再需要的文件拨匆,可以最小化 WAL歸檔的尺寸姆涩。 pg_archivecleanup工具被特別設(shè)計(jì)為在典型單一后備配置下與 archive_cleanup_command共同使用。 不過要注意惭每,如果為備份而使用歸檔骨饿, 有一些文件即使后備服務(wù)器不再需要也需要保留,至少被用來從最后一個(gè)基礎(chǔ)備份恢復(fù)台腥。
恢復(fù)命令文件recovery.conf的簡單例子(認(rèn)證的流復(fù)制宏赘,且清理不需要的wal歸檔):
standby_mode = 'on'
primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass'
restore_command= 'cp /path/to/archive/%f %p'
archive_cleanup_command = 'pg_archivecleanup /path/to/archive %r'
可以有任意數(shù)量的后備服務(wù)器,但如果使用流復(fù)制黎侈, 確保主服務(wù)器上max_wal_senders設(shè)置足夠高察署, 這樣允許它們能同時(shí)連接。
流復(fù)制
流復(fù)制允許一臺(tái)后備服務(wù)器比使用基于文件的日志傳送更能保持最新的狀態(tài)蜓竹。后備服務(wù)器連接到主服務(wù)器箕母,主服務(wù)器則在WAL記錄產(chǎn)生時(shí)將以流式傳送給后備服務(wù)器而不必等到WAL文件被填充。
默認(rèn)情況下流復(fù)制是異步的俱济, 在這種情況下主服務(wù)器上提交一個(gè)事務(wù)與該變化在后備服務(wù)器上可見之間存在短暫的延遲嘶是。這種延遲比基于文件的日志傳送方式中要小得多,在后備服務(wù)器的能力足以跟得上負(fù)載的前提下延遲通常低于一秒蛛碌。在流復(fù)制中聂喇,不需要archive_timeout來縮減數(shù)據(jù)丟失窗口。
如果使用的流復(fù)制沒有基于文件的連續(xù)歸檔蔚携,該服務(wù)器可能在后備機(jī)收到WAL段之前回收這些舊的WAL段希太。如果發(fā)生這種情況,后備機(jī)將需要重新從一個(gè)新的基礎(chǔ)備份初始化酝蜒。通過設(shè)置wal_keep_segments為一個(gè)足夠高的值來確保舊的WAL段不會(huì)被太早重用或者為后備機(jī)配置一個(gè)復(fù)制槽誊辉,可以避免發(fā)生這種情況。如果設(shè)置了一個(gè)后備機(jī)可以訪問的 WAL 歸檔亡脑,就不需要這些解決方案堕澄,因?yàn)樵摎w檔可以為后備機(jī)保留足夠的段邀跃,后備機(jī)總是可以使用該歸檔來追趕主控機(jī)。
要使用流復(fù)制蛙紫,建立一個(gè)基于文件的日志傳送后備服務(wù)器拍屑。 將一個(gè)基于文件日志傳送后備服務(wù)器轉(zhuǎn)變成流復(fù)制后備服務(wù)器的步驟是把 recovery.conf文件中的primary_conninfo設(shè)置指向主服務(wù)器。設(shè)置主服務(wù)器上的listen_addresses和認(rèn)證選項(xiàng) (見pg_hba.conf)坑傅,這樣后備服務(wù)器可以連接到主服務(wù)器上的偽數(shù)據(jù)庫 replication僵驰。
在支持 keepalive 套接字選項(xiàng)的系統(tǒng)上,設(shè)置 tcp_keepalives_idle唁毒、 tcp_keepalives_interval和 tcp_keepalives_count 有助于主服務(wù)器迅速地注意到一個(gè)斷開的連接蒜茴。
設(shè)置來自后備服務(wù)器的并發(fā)連接的最大數(shù)目 (詳見max_wal_senders)。
當(dāng)后備服務(wù)器被啟動(dòng)并且primary_conninfo正確設(shè)置枉证, 后備服務(wù)器將在重放完歸檔中所有可用的 WAL 文件之后連接到主服務(wù)器矮男。 如果連接被成功建立移必,你將在后備服務(wù)器中看到一個(gè)walreceiver進(jìn)程室谚, 并且在主服務(wù)器中有一個(gè)相應(yīng)的walsender進(jìn)程。
1) 認(rèn)證
設(shè)置好用于復(fù)制的訪問權(quán)限非常重要崔泵,這樣只有受信的用戶可以讀取 WAL 流秒赤, 因?yàn)楹苋菀讖?WAL 流中抽取出需要特權(quán)才能訪問的信息。 后備服務(wù)器必須作為一個(gè)超級(jí)用戶或一個(gè)具有REPLICATION 特權(quán)的賬戶向主服務(wù)器認(rèn)證憎瘸。我們推薦為復(fù)制創(chuàng)建一個(gè)專用的具有 REPLICATION和LOGIN特權(quán)的用戶賬戶入篮。 雖然REPLICATION特權(quán)給出了非常高的權(quán)限, 但它不允許用戶修改主系統(tǒng)上的任何數(shù)據(jù)幌甘,而SUPERUSER特權(quán)則可以潮售。
復(fù)制的客戶端認(rèn)證由一個(gè)在database域中指定replication的pg_hba.conf記錄控制。如果后備服務(wù)器運(yùn)行在主機(jī) IP 192.168.1.100 并且用于復(fù)制的賬戶名為foo锅风,管理員可以在主服務(wù)器上向 pg_hba.conf文件增加下列行:
# 允許來自 192.168.1.100 的用戶 "foo" 在提供了正確的口令時(shí)作為一個(gè)
# 復(fù)制后備機(jī)連接到主控機(jī)酥诽。
# TYPE? DATABASE? ? ? ? USER? ? ? ? ? ? ADDRESS? ? ? ? ? ? ? ? METHOD
host? ? replication? ? foo? ? ? ? ? ? 192.168.1.100/32? ? ? ? md5
主服務(wù)器的主機(jī)名和端口號(hào)、連接用戶名和口令在recovery.conf 文件中指定皱埠。在后備服務(wù)器上還可以在~/.pgpass文件中設(shè)置口令 (在database域中指定replication)肮帐。如果主服務(wù)器運(yùn)行在主機(jī) IP 192.168.1.50、端口 5432上边器,用于復(fù)制的賬戶名是foo训枢, 并且口令為foopass,管理員可以在后備服務(wù)器的 recovery.conf文件中增加下列行:
# 后備機(jī)要連接到的主控機(jī)運(yùn)行在主機(jī) 192.168.1.50 上忘巧,
# 端口號(hào)是 5432恒界,連接所用的用戶名是 "foo",口令是 "foopass"砚嘴。
primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass'
2) 監(jiān)控
流復(fù)制的一個(gè)重要健康指標(biāo)是在主服務(wù)器上產(chǎn)生但還沒有在后備服務(wù)器上應(yīng)用的 WAL 記錄數(shù)十酣。 可以通過比較主服務(wù)器上的當(dāng)前 WAL寫位置和后備服務(wù)器接收到的最后一個(gè) WAL位置來計(jì)算這個(gè)滯后量眯勾。 這些位置分別可以用主服務(wù)器上的pg_current_wal_lsn和后備服務(wù)器上的 pg_last_wal_receive_lsn來檢索 。 后備服務(wù)器的最后WAL接收位置也被顯示在 WAL 接收者進(jìn)程的進(jìn)程狀態(tài)中婆誓, 可以使用ps命令查看顯示的狀態(tài)吃环。
可以通過pg_stat_replication 視圖檢索 WAL 發(fā)送者進(jìn)程的列表。pg_current_wal_lsn 與視圖的sent_lsn域之間的巨大差異表示主服務(wù)器承受著巨大的負(fù)載洋幻, 而sent_lsn和后備服務(wù)器上pg_last_wal_receive_lsn 之間的差異可能表示網(wǎng)絡(luò)延遲或者后備服務(wù)器正承受著巨大的負(fù)載郁轻。
復(fù)制槽
復(fù)制槽提供了一種自動(dòng)化的方法來確保主控機(jī)在所有的后備機(jī)收到 WAL 段 之前不會(huì)移除它們,并且主控機(jī)也不會(huì)移除可能導(dǎo)致 恢復(fù)沖突的行文留,即使后備機(jī)斷開也是如此好唯。
作為復(fù)制槽的替代,也可以使用wal_keep_segments 阻止移除舊的 WAL 段燥翅,或者使用archive_command 把段保存在一個(gè)歸檔中骑篙。不過,這些方法常常會(huì)導(dǎo)致保留的 WAL 段比需要的 更多森书,而復(fù)制槽只保留已知所需要的段數(shù)量靶端。這些方法的一個(gè)優(yōu)點(diǎn)是它們?yōu)?pg_wal的空間需求提供了界限,但目前使用復(fù)制槽無法做到凛膏。
類似地杨名,hot_standby_feedback和 vacuum_defer_cleanup_age保護(hù)了相關(guān)行不被 vacuum 移除,但是前者在后備機(jī)斷開期間無法提供保護(hù)猖毫,而后者則需要被設(shè)置為一個(gè)很高 的值以提供足夠的保護(hù)台谍。復(fù)制槽克服了這些缺點(diǎn)。
1) 查詢和操縱復(fù)制槽
每個(gè)復(fù)制槽都有一個(gè)名字吁断,名字可以包含小寫字母趁蕊、數(shù)字和下劃線字符。
已有的復(fù)制槽和它們的狀態(tài)可以在 pg_replication_slots 視圖中看到仔役。
槽可以通過流復(fù)制協(xié)議 或者 SQL 函數(shù)創(chuàng)建并且移除掷伙。
2) 配置實(shí)例
可以這樣創(chuàng)建一個(gè)復(fù)制槽:
postgres=# SELECT * FROM pg_create_physical_replication_slot('node_a_slot');
? slot_name? | lsn
-------------+-----
node_a_slot |
postgres=# SELECT * FROM pg_replication_slots;
? slot_name? | slot_type | datoid | database | active | xmin | restart_lsn | confirmed_flush_lsn
--------+-----+--------+---------+--------+------+----------
node_a_slot | physical? |? ? ? |? ? | f? |? ? |? ? ? |
(1 row)
要配置后備機(jī)使用這個(gè)槽,在后備機(jī)的recovery.conf中應(yīng)該配置 primary_slot_name:
standby_mode = 'on'
primary_conninfo = 'host=192.168.1.50 port=5432 user=foo password=foopass'
primary_slot_name = 'node_a_slot'
級(jí)聯(lián)復(fù)制
級(jí)聯(lián)復(fù)制特性允許一臺(tái)后備服務(wù)器接收復(fù)制連接并且把 WAL 記錄流式傳送給其他后備服務(wù)器骂因, 就像一個(gè)轉(zhuǎn)發(fā)器一樣炎咖。可以被用來減小對(duì)于主控機(jī)的直接連接數(shù)并且使得站點(diǎn)間的帶寬開銷最小化寒波。
一臺(tái)同時(shí)扮演著接收者和發(fā)送者角色的后備服務(wù)器被稱為一臺(tái)級(jí)聯(lián)后備服務(wù)器乘盼。 “更直接”(通過更少的級(jí)聯(lián)后備服務(wù)器)連接到主控機(jī)的后備服務(wù)器被稱為上游服務(wù)器, 而那些離得更遠(yuǎn)的后備服務(wù)器被稱為下游服務(wù)器俄烁。 級(jí)聯(lián)復(fù)制并沒有對(duì)下游服務(wù)器的數(shù)量或分布設(shè)定限制绸栅, 盡管每個(gè)后備服務(wù)器僅連接到一臺(tái)最終連接到單個(gè)主/備服務(wù)器的上游服務(wù)器。
一臺(tái)級(jí)聯(lián)后備服務(wù)器不僅僅發(fā)送從主控機(jī)接收到的 WAL 記錄页屠, 還要發(fā)送那些從歸檔中恢復(fù)的記錄粹胯。因此某些上游連接中的復(fù)制連接被中斷蓖柔, 只要還有新的 WAL 記錄可用,下游的流復(fù)制都會(huì)繼續(xù)下去风纠。
級(jí)聯(lián)復(fù)制目前是異步的况鸣。同步復(fù)制設(shè)置當(dāng)前對(duì)級(jí)聯(lián)復(fù)制無影響。
不管在什么樣的級(jí)聯(lián)布置中竹观,熱備反饋都會(huì)向上游傳播镐捧。
如果一臺(tái)上游后備服務(wù)器被提升為新的主控機(jī),且下游服務(wù)器的 recovery_target_timeline被設(shè)置成'latest'臭增, 下游服務(wù)器將繼續(xù)從新的主控機(jī)得到流懂酱。
要使用級(jí)聯(lián)復(fù)制,要建立級(jí)聯(lián)后備服務(wù)器讓它能夠接受復(fù)制連接(設(shè)置max_wal_senders和hot_standby誊抛, 并且配置基于主機(jī)的認(rèn)證)列牺。 還需要設(shè)置下游后備服務(wù)器中的primary_conninfo指向級(jí)聯(lián)后備服務(wù)器。
同步復(fù)制
PostgreSQL流復(fù)制默認(rèn)是異步的拗窃。如果主服務(wù)器崩潰瞎领, 則某些已被提交的事務(wù)可能還沒有被復(fù)制到后備服務(wù)器,這會(huì)導(dǎo)致數(shù)據(jù)丟失并炮。 數(shù)據(jù)的丟失量與故障轉(zhuǎn)移時(shí)的復(fù)制延遲成比例默刚。
同步復(fù)制能夠保證一個(gè)事務(wù)的所有修改都能被傳送到一臺(tái)同步后備服務(wù)器甥郑。 這擴(kuò)大了由一次事務(wù)提交所提供的標(biāo)準(zhǔn)持久化級(jí)別逃魄。 在計(jì)算機(jī)科學(xué)理論中這種保護(hù)級(jí)別被稱為 2-safe 復(fù)制。
在請(qǐng)求同步復(fù)制時(shí)澜搅,一個(gè)寫事務(wù)的每次提交將一直等待伍俘, 直到收到一個(gè)確認(rèn)表明該提交在主服務(wù)器和后備服務(wù)器上都已經(jīng)被寫入到磁盤上的預(yù)寫日志中。 數(shù)據(jù)會(huì)被丟失的唯一可能性是主服務(wù)器和后備服務(wù)器在同一時(shí)間都崩潰勉躺。 這可以提供更高級(jí)別的持久性癌瘾,盡管只有系統(tǒng)管理員要關(guān)心兩臺(tái)服務(wù)器的放置和管理。 等待確認(rèn)提高了用戶對(duì)于修改不會(huì)丟失的信心饵溅, 但是同時(shí)也不必要地增加了對(duì)請(qǐng)求事務(wù)的響應(yīng)時(shí)間妨退。 最小等待時(shí)間是在主服務(wù)器和后備服務(wù)器之間的來回時(shí)間。
只讀事務(wù)和事務(wù)回滾不需要等待后備服務(wù)器的回復(fù)蜕企。 子事務(wù)提交也不需要等待后備服務(wù)器的響應(yīng)咬荷,只有頂層提交才需要等待。 長時(shí)間運(yùn)行的動(dòng)作(如數(shù)據(jù)載入或索引構(gòu)建)不會(huì)等待最后的提交消息轻掩。 所有兩階段提交動(dòng)作要求提交等待幸乒,包括預(yù)備和提交。
同步備用可以是物理復(fù)制備用或邏輯復(fù)制訂閱者唇牧。 它也可以是任何知道如何發(fā)送適當(dāng)反饋消息的物理或邏輯WAL復(fù)制流消費(fèi)者罕扎。 除了內(nèi)置的物理和邏輯復(fù)制系統(tǒng)之外聚唐,它還包括特殊程序, 如pg_receivewal和pg_recvlogical 以及一些第三方復(fù)制系統(tǒng)和自定義程序腔召。
1) 基本配置
一旦流復(fù)制已經(jīng)被配置杆查,配置同步復(fù)制就只需要一個(gè)額外的配置步驟: synchronous_standby_names必須被設(shè)置為一個(gè)非空值。synchronous_commit也必須被設(shè)置為on臀蛛,但由于這是默認(rèn)值根灯, 通常不需要改變。這樣的配置將導(dǎo)致每一次提交都等待確認(rèn)消息掺栅, 以保證后備服務(wù)器已經(jīng)將提交記錄寫入到持久化存儲(chǔ)中烙肺。 synchronous_commit可以由個(gè)體用戶設(shè)置,因此可以在配置文件中配置氧卧、 可以為特定用戶或數(shù)據(jù)庫配置或者由應(yīng)用動(dòng)態(tài)配置桃笙, 這樣可以在一種每事務(wù)基礎(chǔ)上控制持久性保證。
在一個(gè)提交記錄已經(jīng)在主服務(wù)器上被寫入到磁盤后沙绝,WAL 記錄接著被發(fā)送到后備服務(wù)器搏明。 每次一批新的 WAL 數(shù)據(jù)被寫入到磁盤后,后備服務(wù)器會(huì)發(fā)送回復(fù)消息闪檬, 除非在后備服務(wù)器上wal_receiver_status_interval被設(shè)置為零星著。 如果根據(jù)主服務(wù)器上synchronous_standby_names的設(shè)置將備用服務(wù)器選為同步備用服務(wù)器, 來自該后備的回復(fù)消息將被用來喚醒正在等待提交記錄已被接收確認(rèn)的用戶粗悯。 這些參數(shù)允許管理員指定哪些后備服務(wù)器應(yīng)該是同步后備虚循。 注意同步復(fù)制的配置主要在主控機(jī)上。命名的后備服務(wù)器必須直接連接到主控機(jī)样傍, 主控機(jī)對(duì)使用級(jí)聯(lián)復(fù)制的下游后備服務(wù)器一無所知横缔。
將synchronous_commit設(shè)置為remote_write 將導(dǎo)致每次提交都等待后備服務(wù)器已經(jīng)接收提交記錄并將它寫出到其自身所在的操作系統(tǒng)的確認(rèn), 但并非等待數(shù)據(jù)都被刷出到后備服務(wù)器上的磁盤衫哥。這種設(shè)置提供了比on 要弱一點(diǎn)的持久性保障:在一次操作系統(tǒng)崩潰事件中后備服務(wù)器可能丟失數(shù)據(jù)茎刚, 盡管它不是一次PostgreSQL崩潰。不過撤逢,在實(shí)際中它是一種有用的設(shè)置膛锭, 因?yàn)樗梢詼p少事務(wù)的響應(yīng)時(shí)間。 只有當(dāng)主服務(wù)器和后備服務(wù)器都崩潰并且主服務(wù)器的數(shù)據(jù)庫同時(shí)被損壞的情況下初狰, 數(shù)據(jù)丟失才會(huì)發(fā)生。
把synchronous_commit設(shè)置為remote_apply 將導(dǎo)致每一次提交都會(huì)等待,直到當(dāng)前的同步后備服務(wù)器報(bào)告說它們已經(jīng)重放了該事務(wù), 這樣就會(huì)使該事務(wù)對(duì)用戶查詢可見界睁。在簡單的情況下逾礁, 這允許帶有因果一致性的負(fù)載均衡嘹履。
如果請(qǐng)求一次快速關(guān)閉窒篱,用戶將停止等待霍转。不過岩喷,在使用異步復(fù)制時(shí)迄委, 在所有未解決的 WAL 記錄被傳輸?shù)疆?dāng)前連接的后備服務(wù)器之前硫狞,服務(wù)器將不會(huì)完全關(guān)閉泣侮。
2)多個(gè)同步后備
同步復(fù)制支持一個(gè)或者更多個(gè)同步后備服務(wù)器,事務(wù)將會(huì)等待酬凳, 直到所有同步后備服務(wù)器都確認(rèn)收到了它們的數(shù)據(jù)為止惠况。 事務(wù)必須等待其回復(fù)的同步后備的數(shù)量由synchronous_standby_names指定。 這個(gè)參數(shù)也指定后備服務(wù)器的名稱方法(FIRST和ANY)的列表宁仔, 以從列出的選項(xiàng)中選擇同步備用數(shù)據(jù)庫稠屠。
FIRST方法指定了一個(gè)基于優(yōu)先級(jí)的同步復(fù)制,并使事務(wù)提交等待翎苫, 直到它們的WAL記錄被復(fù)制到根據(jù)其優(yōu)先級(jí)選擇的所請(qǐng)求數(shù)量的同步備用數(shù)據(jù)庫权埠。 其名稱出現(xiàn)在清單前面的備用數(shù)據(jù)庫被賦予更高的優(yōu)先級(jí),并將被視為同步煎谍。 此列表中后面出現(xiàn)的其他備用服務(wù)器代表潛在的同步備用服務(wù)器攘蔽。 如果任何當(dāng)前的同步備用服務(wù)器因任何原因斷開連接, 它將被立即替換為次最高優(yōu)先級(jí)的備用服務(wù)器呐粘。
基于優(yōu)先級(jí)的多個(gè)同步后備的synchronous_standby_names示例為:
synchronous_standby_names = 'FIRST 2 (s1, s2, s3)'
在這個(gè)例子中满俗,如果有四個(gè)后備服務(wù)器s1、s2作岖、 s3和s4在運(yùn)行唆垃,兩個(gè)后備服務(wù)器s1 和s2將被選中為同步后備,因?yàn)樗鼈兂霈F(xiàn)在后備服務(wù)器名稱列表的前部痘儡。 s3是一個(gè)潛在的同步后備辕万,當(dāng)s1或s2 中的任何一個(gè)失效,它就會(huì)取而代之。s4 則是一個(gè)異步后備因?yàn)樗拿植辉诹斜碇小?br>
方法ANY指定基于定額的同步復(fù)制渐尿,并使事務(wù)提交等待醉途, 直到它們的WAL記錄至少被復(fù)制到列表中的所請(qǐng)求數(shù)量的同步備用數(shù)據(jù)庫。
基于定額的多個(gè)同步備用數(shù)據(jù)庫的synchronous_standby_names的一個(gè)例子:
synchronous_standby_names = 'ANY 2 (s1, s2, s3)'
在這個(gè)例子中涡戳,如果有四個(gè)備用服務(wù)器s1结蟋、s2、 s3和s4正在運(yùn)行渔彰,事務(wù)提交將等待來自s1嵌屎、 s2和s3中的任意兩個(gè)備用服務(wù)器的回復(fù)。 s4是一個(gè)異步的備用服務(wù)器恍涂,因?yàn)樗辉诹斜碇?宝惰。
備用服務(wù)器的同步狀態(tài)可以使用pg_stat_replication視圖查看。
)3. 性能規(guī)劃
同步復(fù)制通常要求仔細(xì)地規(guī)劃和放置后備服務(wù)器來保證應(yīng)用能令人滿意地工作再沧。 等待并不利用系統(tǒng)資源尼夺,但是事務(wù)鎖會(huì)持續(xù)保持直到傳輸被確認(rèn)。其結(jié)果是炒瘸, 不小心使用同步復(fù)制將由于響應(yīng)時(shí)間增加以及較高的爭(zhēng)用率而降低數(shù)據(jù)庫應(yīng)用的性能淤堵。
PostgreSQL允許應(yīng)用開發(fā)者通過復(fù)制來指定所要求的持久性級(jí)別。 這可以為整個(gè)系統(tǒng)指定顷扩,不過它也能夠?yàn)樘囟ǖ挠脩艋蜻B接指定拐邪, 甚至還可以為單個(gè)事務(wù)指定。
例如隘截,一個(gè)應(yīng)用的載荷的組成可能是這樣:10% 的改變是重要的客戶詳情扎阶, 而 90% 的改變是不太重要的數(shù)據(jù),即使它們丟失業(yè)務(wù)也比較容易容忍 (例如用戶間的聊天消息)婶芭。
通過在應(yīng)用級(jí)別(在主服務(wù)器上)指定的同步復(fù)制選項(xiàng)东臀, 我們可以為大部分重要的改變提供同步復(fù)制,并且不會(huì)拖慢整體的載荷犀农。 應(yīng)用級(jí)別選項(xiàng)是使高性能應(yīng)用享受同步復(fù)制的一種重要和實(shí)用的工具惰赋。
你應(yīng)該認(rèn)為網(wǎng)絡(luò)帶寬必須比 WAL 數(shù)據(jù)的產(chǎn)生率高。
高可用性規(guī)劃
當(dāng)synchronous_commit被設(shè)置為on或remote_write時(shí)井赌, 發(fā)生的提交將等待直至同步后備服務(wù)器回應(yīng)谤逼。如果上一個(gè)或者唯一一個(gè)后備服務(wù)器崩潰, 響應(yīng)可能不會(huì)發(fā)生仇穗。
防止數(shù)據(jù)丟失的最好解決方案是確保你不會(huì)丟失你的上一個(gè)保持同步的后備服務(wù)器。 這可以通過使用synchronous_standby_names 命名多個(gè)潛在的同步后備服務(wù)器來實(shí)現(xiàn)戚绕。
在基于優(yōu)先級(jí)的同步復(fù)制中纹坐,名稱出現(xiàn)在列表中較早的備用服務(wù)器將用作同步備用服務(wù)器。 如果其中一個(gè)現(xiàn)有的備用服務(wù)器失敗舞丛,在這些之后列出的備用服務(wù)器將接管同步備用服務(wù)器的角色耘子。
在基于定額的同步復(fù)制中果漾,出現(xiàn)在列表中的所有備用服務(wù)器將用作同步備用服務(wù)器的候選項(xiàng)。 即使其中一個(gè)失敗谷誓,其他備用服務(wù)器仍將繼續(xù)扮演同步備用服務(wù)器候選人的角色绒障。
當(dāng)一臺(tái)后備服務(wù)器第一次附加到主服務(wù)器時(shí),它將處于一種還沒有正確同步的狀態(tài)捍歪。 這被描述為追趕模式户辱。一旦后備服務(wù)器和主服務(wù)器之間的遲滯第一次變成零, 我們就來到了實(shí)時(shí)的流式狀態(tài)糙臼。 在后備服務(wù)器被創(chuàng)建之后的很長一段時(shí)間內(nèi)可能都是追趕模式庐镐。如果后備服務(wù)器被關(guān)閉, 則追趕周期將被增加变逃,增加量由后備服務(wù)器被關(guān)閉的時(shí)間長度決定必逆。 只有當(dāng)后備服務(wù)器到達(dá)流式狀態(tài)后,它才能成為一臺(tái)同步后備揽乱。 這個(gè)狀態(tài)可以使用pg_stat_replication視圖查看名眉。
如果在提交正在等待確認(rèn)時(shí)主服務(wù)器重啟, 那些正在等待的事務(wù)將在主數(shù)據(jù)庫恢復(fù)時(shí)被標(biāo)記為完全提交凰棉。 沒有辦法確認(rèn)所有后備服務(wù)器已經(jīng)收到了在主服務(wù)器崩潰時(shí)所有還未處理的 WAL 數(shù)據(jù)损拢。 某些事務(wù)可能不會(huì)在后備服務(wù)器上顯示為已提交,即使它們?cè)谥鞣?wù)器上顯示為已提交渊啰。 我們提供的保證是:在 WAL 數(shù)據(jù)已經(jīng)被后備服務(wù)器安全地收到之前探橱, 應(yīng)用將不會(huì)收到一個(gè)事務(wù)成功提交的顯式確認(rèn)。
如果你真的丟失了你的上一個(gè)后備服務(wù)器绘证,那么你應(yīng)該禁用 synchronous_standby_names并且在主服務(wù)器上重載配置文件隧膏。
如果主服務(wù)器與剩下的后備服務(wù)器是隔離的, 你應(yīng)當(dāng)故障轉(zhuǎn)移到那些其他剩余后備服務(wù)器中的最佳候選者上嚷那。
如果在事務(wù)等待時(shí)你需要重建一臺(tái)后備服務(wù)器胞枕,確保命令 pg_start_backup() 和 pg_stop_backup() 被運(yùn)行在一個(gè)synchronous_commit = off 的會(huì)話中,否則那些請(qǐng)求將永遠(yuǎn)等待后備服務(wù)器出現(xiàn)魏宽。
后備服務(wù)器中的持續(xù)歸檔
當(dāng)在備用數(shù)據(jù)庫中使用連續(xù)WAL歸檔時(shí)腐泻,有兩種不同的情況: WAL歸檔可以在主數(shù)據(jù)庫和備用數(shù)據(jù)庫之間共享,或者備用數(shù)據(jù)庫可以有自己的WAL歸檔队询。 當(dāng)備用數(shù)據(jù)庫具有自己的WAL歸檔時(shí)派桩,將archive_mode設(shè)置為 always,并且備用數(shù)據(jù)庫將為每個(gè)收到的WAL段調(diào)用歸檔命令蚌斩, 無論是從歸檔恢復(fù)或通過流復(fù)制铆惑。可以類似地處理共享歸檔,但是 archive_command必須測(cè)試正在歸檔的文件是否已存在员魏, 以及現(xiàn)有文件是否具有相同的內(nèi)容丑蛤。這需要在archive_command 中更加小心,因?yàn)樗仨毿⌒牟灰采w具有不同內(nèi)容的現(xiàn)有文件撕阎, 但如果完全相同的文件存檔兩次受裹,則返回成功。 如果兩個(gè)服務(wù)器試圖同時(shí)歸檔同一個(gè)文件虏束,則所有必須無競(jìng)爭(zhēng)的完成棉饶。
如果archive_mode設(shè)置為on, 則在恢復(fù)或者待機(jī)模式期間不會(huì)啟用歸檔程序魄眉。如果備用服務(wù)器已升級(jí)砰盐, 它將在升級(jí)后開始?xì)w檔,但不會(huì)歸檔其未生成的任何WAL坑律。 要在歸檔中獲取完整的WAL文件系列岩梳,必須確保所有WAL在到達(dá)備用數(shù)據(jù)庫之前都已存檔。 這對(duì)于基于文件的日志傳送是固有的晃择,因?yàn)閭溆脭?shù)據(jù)庫只能恢復(fù)在歸檔中找到的文件冀值, 但是如果啟用了流復(fù)制,則不會(huì)宫屠。當(dāng)服務(wù)器不處于恢復(fù)模式時(shí)列疗, on和always模式之間沒有區(qū)別