您好,登錄后才能下訂單哦!
這篇文章給大家介紹什么是主從復制,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
復制的方式
在集群中實現復制主要通過兩種方式:
狀態轉移(State Transfer):主機(Primary)將自己所有的狀態,拷貝并發送給備機(Backup),一般是增量備份;
復制狀態機(Replicated State Machine):將備機視為一個確定的狀態機——client 發送操作到主機,主機按順序發送到備機,所有備機執行所有的操作,如果從同一起始狀態,以相同的順序輸入相同的操作,它們的輸出將是相同的。
VMware FT 使用了復制狀態機的方法。
狀態轉移傳輸的可能是內存,而復制狀態機傳輸來自客戶端的操作或者其他外部事件,人們傾向于使用復制狀態機的原因是,外部操作或事件通常比服務的內存狀態要小。例如,如果是一個數據庫,它的內存狀態可能達到 GB 級別。
復制的挑戰
要考慮的幾個 Big Question:
我們要復制哪些狀態?
主機必須等待備機備份完嗎?
什么時候切換到備機?
切換時能否看到異常情況?
如果有個副本故障了,我們需要重新添加一個新的副本,這可能是一個代價很高的行為,因為副本可能非常大,如何提升添加新副本的速度?
讓我們看看虛擬化巨頭 VMware 是怎么做的。
VMware FT 論文總結
總覽
如圖 1,約定:主虛擬機(Primary VM)簡稱為主機,Backup VM 簡稱為備機。
VMware FT 需要兩臺物理服務器,主機與備機保持同步,虛擬機的虛擬磁盤在共享存儲上。
所有的輸入(如網絡、鼠標、鍵盤等)都會輸入到主機,然后通過 Logging channel 轉發到備機,對于非確定性的操作,還將發送額外的信息,確保備機以確定性的方式執行這些操作。
兩臺虛擬機都會執行輸入操作,但只有主機的輸出會返回客戶端,備機的輸出會被管理程序丟棄。
確定性重放(Deterministic replay)
不確定性(Non-Deterministic)事件比如虛擬中斷,不確定性操作比如從處理器讀取時鐘周期計數器,可能會讓主機和備機的運行結果不一樣。
這帶來三個挑戰:
正確捕獲所有輸入和必要的不確定性輸入來保證備機確定性執行;
正確在備機執行不確定性輸入;
不降低系統的性能;
VMware 確定性重放(deterministic replay)能夠捕獲所有輸入和可能的不確定性輸入,并寫到日志文件記錄下來。通過讀取日志文件,可以準確重放虛擬機的執行。
對于不確定性輸入,必須記錄足夠的信息來重放,但是論文中沒有描述具體的日志格式,Robert 教授猜測可能有三種記錄:
事件發生時的指令序號;
日志類型。可能是普通的網絡數據輸入,也可能是怪異的指令;
數據。
FT 協議(FT Protocol)
VMware FT 通過確定性重放來產生相關的日志條目,但不將日志寫入磁盤,而是通過 logging channel 發送給備機。備機實時重放日志項。
為了容錯,必須在 loggin channel 上實現嚴格的容錯協議,有以下要求:
輸出要求:如果備機在主機故障后接管,備機將以和主機已經向外界發送的輸出完全一致的方式繼續運行。
最簡單的方式是對每一個輸出操作創建一個特殊的日志項。
但有一種情況,假設虛擬機運行的是數據庫,主機備機的數據都是 10。現在客戶端發送自增請求,主機做了 +1 并回復給客戶端 11,之后馬上宕機了,更糟糕的是主機發送給備機的 +1 操作也丟包了。這時候備機還是 10,并接管了主機的工作,客戶端再次請求 +1,又會收到 11 的回復。客戶端會得到一個怪異的結果(自增兩次還是 11)。
所以要求:
輸出規則:主機直到備機接收并確認了和輸出相關的日志的時候,才發送輸出給外界。
這樣做的目的是,只要備機收到了所有的日志條目,即使主機宕機了,備機仍能夠重放到客戶端最后看到的狀態。
如圖 2 所示,向外界的輸出會被延遲,直到主機收到來自備機的確認。
幾乎每一個復制系統都有這個問題:在某個時間點,主機必須停下來等待備機,這肯定會限制性能。
注意:因為沒有兩階段提交事務,不能保證所有的輸出只被生成一次。備機無法判斷主機是在宕機之前還是之后發送了最后的輸出,備機可能會重新執行一次輸出操作。不過,VMware 通過其網絡基礎設施來檢測重復數據包,并防止輸出重傳到客戶端。
發現與處理故障
主機和備機必須快速知道另一方故障,通過 udp 心跳包和監控 logging channel 上的流量相結合來檢測,如果心跳超時或 logging channel 流量停止則表明故障。
如果備機故障,主機就會停止向 logging channel 發送日志,繼續正常運行。
在這之后備機怎么追上主機呢?VMware有一個工具叫 VMotion,它能夠在最小程度上中斷虛擬機的執行,克隆一個虛擬機。
如果主機故障,備機必須先重放,直到消耗完最后一個日志項。然后備機接替主機,開始向客戶端生產輸出。
為了確保一次只有一個虛擬機成為主機,避免出現腦裂,VMware 在共享存儲上執行一個原子的 test-and-set 鎖指令。該操作每次只能對其中一臺機器返回成功,這在主機和備機因為網絡分區都想接替工作時很有用。但如果共享存儲因為網絡問題不能訪問,那么無論如何都不能正常工作。
當其中一臺虛擬機發生故障時,VMware FT 會在另一臺物理機上自動啟動新的備份虛擬機來恢復冗余。
FT 的實際實現細節
上一節描述了容錯的基礎設計和協議,但為了創建一個可用的、健壯的自動化系統,還需要設計和實現許多其他組件。
啟動和重啟 FT VMs
一個挑戰是,如何在主機運行時,以和主機相同的狀態啟動備機?為了解決這個問題,VMware 提供一個名為 VMware VMotion 的工具,允許在最小化中斷的代價下,將運行中的虛擬機從一臺服務器遷移到另一臺服務器。為了容錯,該工具被重新設計為 FT VMotion,以允許將虛擬機克隆到遠程主機上,這種克隆操作打斷主機的時間不超過 1 秒。
管理 Logging Channel
上圖 3 說明了日志從主機產生到在備機上消費的過程。
虛擬機管理程序維護了一個大的日志緩沖(log buffer),保存主機和備機的日志。主機會產生日志項到日志緩沖,備機從日志緩沖消費日志。
如果備機讀到空的日志緩沖,則會暫停運行直到日志緩沖有日志;如果主機寫日志的時候發現日志緩沖滿了,也會暫停運行直到日志項被清除——這種暫停會影響虛擬機的客戶端。因此,我們的實現必須最小化主機日志緩沖寫滿的可能性。
通常,主機日志緩沖滿的原因:
帶寬太小,建議日志通道帶寬 1Gbit/s;
備機執行速度太慢,從而消費日志太慢時,主機的日志緩沖也可能會被填滿;
在 VMware FT 中已經實現了一種機制,當備機遠遠落后時(根據論文中的說法,落后超過1秒),可以減緩主機的執行速度。通過減少主機的 CPU 資源來減慢速度。
注意對于主機的減速是很罕見的,通常只在系統處于極端壓力的情況下發生。
磁盤 IO 實現問題
有一些和磁盤 IO 相關的細微的實現問題。
問題 1:非阻塞的磁盤操作可以并行執行,因此對同一磁盤位置的同時訪問可能導致不確定性。
解決方案:檢測所有這類 IO 競爭,然后強制這些競爭的磁盤操作以相同的方式在主機和備機上順序執行。
怎么檢測?論文也沒說。
問題 2:虛擬機上的應用程序(或操作系統)的磁盤操作也可能導致內存的競爭
解決方案:通過 Bounce buffer—— 一個和磁盤操作正在訪問的內存大小一致的臨時緩沖來解決。磁盤讀操作被修改為在 bounce buffer 中讀取特定數據,并且數據僅在IO操作完成并傳遞完成的時候拷貝到虛擬機內存。類似的,對于磁盤寫操作,將要被發送的數據會先拷貝到 bounce buffer,磁盤寫操作修改為寫數據到 bounce buffer。
Bounce buffer 的使用會減慢磁盤操作,但是論文表示還沒有看到任何明顯的性能差異。
問題3:磁盤 IO 因主機故障在主機上沒有完成,備份接管后怎么辦?
解決方案:發送錯誤來表明 IO 失敗,然后重試錯誤的 IO。
替代方案
本節討論一些替代方案,以及他們所做的權衡。
共享磁盤與非共享磁盤:VMware FT 使用了一個主備機都能訪問的共享存儲。一個替代方案是使用單獨(非共享)的虛擬磁盤,主備機分別寫入這些磁盤。這種設計可以用在共享存儲不能同時被主、備機訪問,或者共享存儲太貴的情況下。缺點是需要做額外的工作,必須同步磁盤狀態。
在備機上執行磁盤讀取:在目前實現中,備機絕不會從磁盤進行讀取,磁盤操作被認為是一種輸入。一個替代的設計是,備機可以執行磁盤讀取,當有大量磁盤讀的工作負載時,這種方法可以幫助減少日志通道的流量。然而,這種方法有兩個主要挑戰:
可能會減慢備機的執行速度,因為備機必須執行所有的磁盤讀;
如果讀取在主機上成功,但在備機上失敗(反之亦然)怎么辦?必須做一些額外的工作來處理失敗的磁盤讀操作。
VMware 的性能評估顯示,在備機上執行磁盤讀取會降低 1-4% 的吞吐量,但同時也降低了日志帶寬。
FAQ
來自:https://pdos.csail.mit.edu/6.824/papers/vm-ft-faq.txt
Q: GFS 和 VMware FT 都提供了容錯性,哪一個更好?
FT 提供計算容錯,你能用它為任何已有的網絡服務器提供容錯性。FT 提供了相當嚴格的一致性而且對客戶端和服務器都是透明的。例如,你可以將 FT 應用于一個已有的郵件服務器并為其提供容錯性。
GFS 只提供存儲容錯,因為 GFS 只針對特定的簡單服務(存儲)提供容錯性,它的備份策略會比 FT 更高效。例如,GFS 不需要使中斷都以完全相同的指令發生在所有的副本上。GFS 通常只會用于一個對外提供完整容錯服務的系統的一部分。例如,VMware FT 本身也依賴了一個在主備機間共享的有容錯性的存儲服務,而你則可以用類似于 GFS 的東西來實現這個共享存儲(雖然從細節上來講 GFS 不太適用于 FT)。
Q: 共享存儲上的原子 test-and-set 指令是什么?
在共享存儲上的一個服務,最初狀態為 false,主機或備機認為對方宕機了,自己應該接管的時候,首先要向共享存儲發送一個 test-and-set 操作,偽代碼是:
test-and-set() { acquire_lock() if flag == true: release_lock() return false else: flag = true release_lock() return true
只有當返回 true 時才能接管主機。主要為了避免當主、備機出現網絡分區,都想接管時出現腦裂(即同時有兩個主機)的情況。
這有點像一個分布式鎖。問題是:偽代碼沒有展示什么時候 flag會被設為 false!
老師解釋:論文沒有提及什么時候將 flag 重設為 false,也許是管理員人為的操作,也許是交給機器來清理。
關于什么是主從復制就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。