介紹
前段時間,我接到了開發故障轉移集群的任務
這一決定提出了一個合理的問題:故障轉移集群的容錯能力如何? 為了研究這個問題,我開發了一個測試平台,模擬集群節點上的各種故障,等待服務恢復,恢復故障節點,並繼續循環測試。 這個項目最初被稱為 hapgsql,但隨著時間的推移,我厭倦了這個只有一個元音的名字。 因此,我開始調用容錯數據庫(以及指向它們的浮動IP) 克羅根 (計算機遊戲中的角色,其中所有重要器官都被複製),並且節點、集群和項目本身是 圖昌卡 (克洛根人居住的星球)。
現在管理層已經允許
集群部署在虛擬機上
精準授時服務 ntpd
(孤兒模式)。 共享服務器 見證 充當中央 NTP 服務器,將其時間分配給所有集群,從而使所有服務器相互同步。 如果 見證 發生故障或變得孤立,然後集群服務器之一(集群內)將開始分配其時間。 輔助緩存 HTTP代理 也提升至 見證,在它的幫助下,其他虛擬機可以訪問 Yum 存儲庫。 實際上,準確時間和代理等服務很可能託管在專用服務器上,但在展位中它們託管在 見證 只是為了節省虛擬機數量和空間。
版本
v0。 適用於 VirtualBox 7 上的 CentOS 11 和 PostgreSQL 6.1。
簇結構
所有集群均設計為位於多個數據中心,組合成一個扁平網絡,並且必須能夠承受單個數據中心的故障或網絡隔離。 這就是為什麼 不可能 用於防護 裂腦 標準起搏器技術稱為 斯托尼斯 (射擊另一個節點的頭部)或 擊劍。 其本質是:如果集群中的節點開始懷疑某個節點出現問題,沒有響應或行為不正確,那麼它們會通過“外部”設備(例如 IPMI 或 UPS 控制卡)強制將其關閉。 但這僅適用於在發生單一故障時 IPMI 或 UPS 服務器繼續工作的情況。 在這裡,我們計劃在整個數據中心發生故障(例如斷電)時防止發生更災難性的故障。 有了這樣的拒絕,一切 斯托尼斯- 設備(IPMI、UPS 等)也將無法工作。
相反,該系統是基於法定人數的思想。 所有節點都有發言權,只有能看到半數以上節點的節點才能工作。 這個“一半+1”的數量稱為 法定人數。 如果未達到法定人數,則節點決定其處於網絡隔離狀態,並且必須關閉其資源,即就是這樣 裂腦保護。 如果負責此行為的軟件無法工作,則必須使用看門狗(例如基於 IPMI 的看門狗)來工作。
如果節點數量為偶數(一個集群在兩個數據中心),那麼可能會出現所謂的不確定性 50%/ 50% (五五十)當網絡隔離將集群正好分成兩半時。 因此,對於偶數個節點,我們添加 法定設備 是一個要求不高的守護進程,可以在第三個數據中心的最便宜的虛擬機上啟動。 他將票投給其中一個片段(他看到的),從而解決了 50%/50% 的不確定性。 我命名了將啟動仲裁設備的服務器 見證 (repmgr 的術語,我喜歡它)。
資源可以從一個地方移動到另一個地方,例如,從有故障的服務器到健康的服務器,或者根據系統管理員的命令。 以便客戶知道他們需要的資源位於哪裡(連接到哪裡?), 浮動IP (浮動IP)。 這些是 Pacemaker 可以在節點之間移動的 IP(一切都在平面網絡上)。 它們中的每一個都像徵著一種資源(服務),並將位於您需要連接才能訪問該服務的位置(在我們的例子中是數據庫)。
Tuchanka1(壓縮電路)
結構
我們的想法是,我們有很多低負載的小型數據庫,為此維護一個熱備模式的專用從服務器來進行只讀事務是無利可圖的(沒有必要如此浪費資源)。
每個數據中心有一台服務器。 每台服務器都有兩個PostgreSQL 實例(在PostgreSQL 術語中,它們被稱為集群,但為了避免混淆,我將它們稱為實例(與其他數據庫類比),而我只會將Pacemaker 集群稱為集群) 。 一個實例運行在master模式,只有它提供服務(只有浮動IP通向它)。 第二個實例作為第二個數據中心的從屬實例,僅在其主實例發生故障時才提供服務。 由於大多數時候只有兩個實例(主實例)中的一個會提供服務(執行請求),因此所有服務器資源都會針對主實例進行優化(內存分配給shared_buffers緩存等),但這樣第二個實例在其中一個數據中心發生故障的情況下,還擁有足夠的資源(儘管通過文件系統緩存進行次優操作)。 在集群正常運行期間,Slave不提供服務(不執行只讀請求),這樣就不會與同一台機器上的Master爭奪資源。
在兩個節點的情況下,容錯只能通過異步複製實現,因為通過同步複製,從站的故障將導致主站的停止。
未能見證
未能見證(法定設備)我只會考慮 Tuchanka1 集群,對於所有其他集群來說,情況都是一樣的。 如果見證失敗,集群結構不會發生任何變化,一切都將繼續以原來的方式工作。 但法定人數將變為 2 中的 3,因此任何後續故障對於集群來說都將是致命的。 它仍然需要緊急修復。
圖昌卡1 拒絕
Tuchanka1 的一個數據中心發生故障。 在這種情況下 見證 將其投票給第二個數據中心的第二個節點。 在那裡,以前的從站變成了主站,因此,兩個主站都在同一台服務器上工作,並且它們的兩個浮動IP都指向它們。
圖昌卡2(古典)
結構
兩個節點的經典方案。 主人在其中之一工作,奴隸在第二個上工作。 兩者都可以執行請求(從機是只讀的),因此兩者都由浮動 IP 指向:krogan2 是主機,krogan2s1 是從機。 主從機都會有容錯能力。
在兩個節點的情況下,容錯只能通過異步複製實現,因為同步複製時,slave的故障會導致master的停止。
圖昌卡2 拒絕
如果其中一個數據中心發生故障 見證 投票給第二個。 在唯一工作的數據中心上,主站將被提升,並且兩個浮動IP將指向它:主站和從站。 當然,實例的配置方式必須使其具有足夠的資源(連接限制等)以同時接受來自主從浮動IP的所有連接和請求。 也就是說,在正常操作期間,它應該有足夠的限制供應。
Tuchanka4(許多奴隸)
結構
已經是另一個極端了。 有些數據庫會收到大量只讀請求(高負載站點的典型情況)。 Tuchanka4 是一種可能有三個或更多從站來處理此類請求的情況,但仍然不會太多。 由於從站數量非常多,因此有必要發明分層複製系統。 在最小情況下(如圖所示),兩個數據中心各有兩台服務器,每台服務器都有一個 PostgreSQL 實例。
該方案的另一個特點是已經可以組織一次同步複製。 如果可能,它被配置為複製到另一個數據中心,而不是複製到與主數據中心相同的數據中心的副本。 主站和每個從站都由一個浮動IP指向。 幸運的是,在從屬之間有必要以某種方式平衡請求 SQL代理,例如,在客戶端。 不同類型的客戶可能需要不同的類型 SQL代理,並且只有客戶端開發人員知道誰需要哪個。 該功能可以通過外部守護程序或客戶端庫(連接池)等來實現。 所有這些都超出了故障轉移數據庫集群(故障轉移 SQL代理 可以獨立實現,與客戶端容錯一起實現)。
圖昌卡4 拒絕
如果一個數據中心(即兩台服務器)發生故障,見證人將投票支持第二個數據中心。 這樣一來,第二個數據中心就有兩台服務器在運行:一台運行master,master浮動IP指向它(用於接收讀寫請求);另一台運行master,master浮動IP指向它(用於接收讀寫請求); 在第二台服務器上有一個運行同步複製的從屬服務器,並且其中一個從屬浮動 IP 指向它(用於只讀請求)。
首先要注意的是,並非所有從屬浮動 IP 都會成為工作人員,而只有一個。 為了正確地使用它,有必要 SQL代理 將所有請求重定向到僅存的浮動IP; 而如果 SQL代理 否,那麼您可以在連接 URL 中列出所有以逗號分隔的浮動 IP 從站。 在這種情況下,與 庫 連接將連接到第一個工作 IP,這是在自動測試系統中完成的。 也許在其他庫中,例如 JDBC,這將不起作用並且是必要的 SQL代理。 這樣做是因為禁止在一台服務器上同時提高從屬服務器的浮動 IP,以便在有多個從屬服務器運行時,它們會均勻地分佈在從屬服務器之間。
第二:即使在數據中心發生故障的情況下,也會保持同步複製。 並且即使發生二次故障,即剩餘數據中心的兩台服務器之一發生故障,集群雖然會停止提供服務,但仍會保留所有已提交確認的已提交事務的信息(二次故障不會有丟失信息)。
Tuchanka3(3 個數據中心)
結構
這是一個集群,適用於具有三個功能齊全的數據中心的情況,每個數據中心都有一個功能齊全的數據庫服務器。 在這種情況下 法定設備 不需要。 一個數據中心由主站負責,另外兩個數據中心由從站負責。 複製是同步的,類型ANY(slave1,slave2),即當任何一個slave第一個響應他已接受提交時,客戶端都會收到提交確認。 資源由主設備的 4 個浮動 IP 和從設備的 XNUMX 個浮動 IP 表示。 與 TuchankaXNUMX 不同,所有三個浮動 IP 都是容錯的。 要平衡只讀 SQL 查詢,您可以使用 SQL代理 (具有單獨的容錯功能),或者將一個從浮動 IP 分配給一半客戶端,將另一半分配給第二個客戶端。
圖昌卡3 拒絕
如果其中一個數據中心發生故障,則剩下兩個。 在第一種情況下,主設備和來自主設備的浮動IP 被提升,在第二種情況下,從設備和兩個從設備浮動IP 都被提升(實例必須具有雙重資源保留,以便接受來自兩個從設備浮動IP 的所有連接)。 主從之間的同步複製。 此外,當兩個數據中心被破壞時(如果它們不是同時被破壞),集群將保存已提交和確認的事務信息(不會丟失信息)。
我決定不包含文件結構和部署的詳細描述。 任何想要嘗試的人都可以閱讀 README 中的全部內容。 我只是提供自動化測試的描述。
自動測試系統
為了通過模擬各種故障來測試集群的容錯能力,創建了自動測試系統。 通過腳本啟動 test/failure
。 該腳本可以將要測試的集群數量作為參數。 例如這個命令:
test/failure 2 3
將僅測試第二個和第三個集群。 如果未指定參數,則將測試所有集群。 所有集群都會並行測試,結果顯示在 tmux 面板中。 Tmux 使用專用的 tmux 服務器,因此可以從默認 tmux 下運行腳本,從而產生嵌套的 tmux。 我建議在大窗口中使用小字體的終端。 在測試開始之前,所有虛擬機都會回滾到腳本完成時的快照 setup
.
終端根據正在測試的集群數量分為幾列;默認情況下(在屏幕截圖中)有四個。 我將使用 Tuchanka2 的示例來描述各列的內容。 屏幕截圖中的面板已編號:
- 此處顯示測試統計數據。 列:
- 失敗 — 模擬故障的測試(腳本中的函數)的名稱。
- 反應 — 集群恢復其功能的算術平均時間(以秒為單位)。 它是從模擬故障的腳本開始到集群恢復其功能並能夠繼續提供服務的那一刻進行測量的。 如果時間很短,例如六秒(這種情況發生在有多個從站(Tuchanka3和Tuchanka4)的集群中),這意味著故障在異步從站上,並且不會以任何方式影響性能;沒有集群狀態切換。
- 偏差 — 顯示值的分佈(準確性) 反應 使用標準差法。
- 數 — 該測試進行了多少次。
- 簡短的日誌允許您評估集群當前正在執行的操作。 顯示迭代(測試)編號、時間戳和操作名稱。 運行時間太長(> 5 分鐘)表明存在問題。
- 心 (心)- 當前時間。 用於視覺評估性能 馬斯特拉 使用浮動 IP 主站將當前時間不斷寫入其表中。 如果成功,結果將顯示在此面板中。
- 擊敗 (pulse) - “當前時間”,之前由腳本記錄 心 掌握,現在閱讀 奴隸 通過其浮動IP。 允許您直觀地評估從屬和復制的性能。 Tuchanka1中沒有浮動IP的從站(沒有提供服務的從站),但是有兩個實例(DB),所以這裡不會顯示 擊敗和 心 第二審。
- 使用該實用程序監控集群運行狀況
pcs mon
。 顯示結構、跨節點的資源分佈以及其他有用信息。 - 此處顯示集群中每個虛擬機的系統監控。 根據集群擁有的虛擬機數量,可能會有更多這樣的面板。 兩張圖 CPU負載 (虛擬機有兩個處理器)、虛擬機名稱、 系統負載 (之所以稱為“平均負載”,是因為它是 5 分鐘、10 分鐘和 15 分鐘的平均值)、進程數據和內存分配。
- 執行測試的腳本的跟踪。 如果發生故障 - 操作突然中斷或無休止的等待週期 - 您可以在此處查看此行為的原因。
測試分兩個階段進行。 首先,該腳本會進行所有類型的測試,隨機選擇要應用此測試的虛擬機。 然後進行無限循環的測試,每次都是隨機選擇虛擬機和故障。 測試腳本突然終止(底部面板)或無限循環等待某事(一項操作的執行時間> 5 分鐘,這可以在跟踪中看到)表明該集群上的某些測試已失敗。
每個測試由以下操作組成:
- 啟動模擬故障的功能。
- 準備好了嗎? — 等待集群恢復(當所有服務都提供時)。
- 顯示集群恢復超時(反應).
- 固定 — 集群正在“修復”。 之後,它應該返回到完全運行狀態並為下一次故障做好準備。
以下是測試列表,並描述了它們的作用:
- 叉子炸彈:使用叉子炸彈製造“內存不足”。
- 太空之外: 硬盤已滿。 但測試相當具有像徵意義;由於測試過程中產生的負載微不足道,因此當硬盤驅動器已滿時,PostgreSQL通常不會失敗。
- Postgres-KILL: 使用命令殺死 PostgreSQL
killall -KILL postgres
. - Postgres-STOP: 掛起 PostgreSQL 命令
killall -STOP postgres
. - 關機:使用命令“斷電”虛擬機
VBoxManage controlvm "виртуалка" poweroff
. - 重設:使用命令使虛擬機超載
VBoxManage controlvm "виртуалка" reset
. - SBD停止:使用命令暫停 SBD 惡魔
killall -STOP sbd
. - 關機:通過SSH向虛擬機發送命令
systemctl poweroff
,系統正常關閉。 - 取消鏈接:網絡隔離、命令
VBoxManage controlvm "виртуалка" setlinkstate1 off
.
使用標準 tmux 命令“kill-window”完成測試 Ctrl-b &,或“分離客戶端”命令 Ctrl-b d:至此測試結束,tmux關閉,虛擬機關閉。
測試過程中發現的問題
-
此時此刻 看門狗惡魔sbd 致力於停止觀察到的守護進程,但不凍結它們。 因此,僅導致凍結的故障 科羅同步 и 起搏器,但不懸掛 sbd。 用於檢查 科羅同步 已經
PR#83 (在 GitHub 上 sbd) , 接受到線程 主。 他們承諾(在 PR#83 中)Pacemaker 會有類似的東西,我希望通過 紅帽8 會做。 但這種“故障”是推測性的,可以很容易地進行人工模擬,例如:killall -STOP corosync
,但在現實生活中從未見過面。 -
У 起搏器 在版本中 CentOS 7的 設置不正確 同步超時 у 法定設備, 因此
如果一個節點發生故障,第二個節點有可能也會重新啟動 ,主人應該移動到那裡。 擴大治愈 同步超時 у 法定設備 部署期間(在腳本中setup/setup1
)。 此修改未獲開發商接受 起搏器相反,他們承諾以這種方式(在某個未指定的未來)重新設計基礎設施,以便自動計算超時。 -
如果數據庫配置指定
LC_MESSAGES
(文本消息)可以使用 Unicode,例如ru_RU.UTF-8
,然後在啟動時 Postgres的 在語言環境不是 UTF-8 的環境中,例如在空環境中(此處 起搏器+數據庫管理系統(paf) 運行 Postgres的), 那日誌將包含問號而不是 UTF-8 字母 。 PostgreSQL 開發人員尚未就這種情況下該怎麼做達成一致。 需要付費,需要安裝LC_MESSAGES=en_US.UTF-8
配置(創建)數據庫實例時。 -
如果設置了wal_receiver_timeout(默認為60s),則在tuchanka3和tuchanka4集群中的master上進行PostgreSQL-STOP測試期間
複製不會重新連接到新的主服務器 。 那裡的複制是同步的,所以不僅slave停止了,新的master也停止了。 通過在配置 PostgreSQL 時設置 wal_receiver_timeout=0 來解決此問題。 -
有時,我在 ForkBomb 測試中觀察到 PostgreSQL 中的複制凍結(內存溢出)。
ForkBomb 之後,有時從站可能無法重新連接到新的主站 。 我只在tuchanka3和tuchanka4集群中遇到過這種情況,其中master由於同步複製而凍結。 很長一段時間(大約兩個小時)後問題自行消失。 需要更多的研究來糾正這個問題。 這些症狀與之前的錯誤類似,雖然是由不同的原因引起的,但具有相同的後果。
克洛根圖片取自
來源: www.habr.com