Bayou復制分布式存儲系統


本文主要參考文獻[1]完成。

第1章導讀

Bayou是一個復制的、弱一致性的存儲系統,用於移動計算環境。為了最大化可用性,Bayou為用戶提供了可以任意讀寫訪問的副本。Bayou的設計側重於為應用程序提供一套檢查和解決更新沖突的機制,確保整個系統趨向最終一致性。Bayou提供了一套協議,通過這個協議,解決沖突時可以使系統保持一致。

Bayou的沖突檢測方法被稱為依賴性檢查。為了保證最終一致性,bayou 服務器必須能夠回滾先前執行的寫操作的效果,並根據全局序列化順序重做它們。此外,bayou 允許客戶端觀察服務器接收到的所有寫操作的結果,包括尚未最終解決沖突的暫時寫操作。

Bayou復制存儲系統的目標是支持各種非實時協作性的應用,諸如日歷、電子郵件、書目數據庫等。

bayou的目標是為處於不可靠網絡連接狀態下的移動設備構建一個滿足最終一致性的分布式存儲系統。bayou不能保證應用程序讀寫的數據一定是處於一致性狀態的。

第2章 Bayou基本系統模型

在 Bayou系統中,部署在服務器(虛擬服務器,非實體服務器)中的每個data collection(數據收集中心)都是一份完整的備份。客戶端通過Bayou提供的API與數據中心進行交互。這些基於RPC實現的API提供了兩個基本功能:讀和寫。
image_57

在Bayou系統中,客戶端和服務器可以同時運行在同一個主機中。Bayou中的server在接受client的寫請求之后,client並不會等待server與其他server進行同步。因為Bayou是弱一致性的,要盡可能提高系統可用性(availability)、簡易性(simplicity)、可伸縮性(scalability).

雖然單獨的讀寫操作是在單個服務器上執行的,但是客戶機不必局限於與單個服務器進行交互。實際上,在移動計算環境中,服務器之間的切換通常是可取的,bayou 提供會話保證,以減少訪問不同服務器時客戶端觀察到的不一致。

為了在各個server之間處理沖突,server會為每個寫操作提供一個全局唯一的WriteID。該ID由第一個接受該寫請求的server提供。每個服務器在本地執行寫操作時都會執行沖突檢測和解決。

為了盡可能減少服務器之間的網絡通信,bayou僅在成對通信的節點間傳播寫操作,這被稱之為anti-entropy 會話。

第3章 沖突檢測與解決

沖突檢測的難點:粒度選擇。如果粒度選擇過大,如將一個文件作為粒度,將會出現文件替換情況導致數據丟失;如果粒度過小,如將每次操作記錄作為粒度,將會檢測不出來沖突。因此沖突的定義需要由應用程序來定義。

Bayou提供了依賴檢查(dependency checks)來檢查沖突,采用合並過程(merge procedures)來處理沖突。

Bayou_Write(update, dependency_check, mergeproc){
    if(DB_Eval(dependency_check.query) != dependency_check.expected_result)
    {
        resolved_update = Interpret(mergeproc);
    }
    else
    {
        resolved_update = update;
    }
    DB_Apply(resolved_update);
}

本質上,bayou系統要求應用開發者向Bayou_Write傳入三個函數指針,分別執行更新、沖突檢查和合並過程。即,bayou只是將三個函數進行打包成一個寫操作,在后文中的所有對寫操作的描述都是對Bayou_Write的描述。

3.1依賴檢查

與應用相關的沖突檢測是通過Bayou系統的依賴檢查實現的。每個寫操作都包含一個依賴檢查,每個依賴檢查是由程序提供的查詢語句和它期望的結果組成的。當服務器執行的查詢語句與所擁有的數據副本不吻合時,將不會返回期望的結果,這樣就檢測到了沖突。這種依賴檢查是執行更新操作的前提條件。如果依賴檢查失敗,將不會執行該更新操作,而是開始執行合並過程以解決沖突。依賴檢查可以檢測讀寫沖突。

3.2合並過程

在寫操作中會提供一個合並過程以供檢測到沖突時解決沖突調用。該合並過程是使用高語義的解釋型語言實現的。

在實踐中,Bayou合並過程是由應用程序開發者以模板的形式編寫的。模板實例化時需要為每個write填充實現細節。

應用程序的用戶不需要知道合並過程,除非程序無法解決沖突。在無法實現自動解決的情況下,合並過程仍將運行到完成,但預計將產生一個經過修訂的更新,以某種方式記錄檢測到的沖突,使用戶能夠在稍后解決沖突。為了實現手動解決,可能使用交互式合並工具,必須以允許用戶理解所發生的事情的方式向用戶呈現沖突的更新。按照慣例,大多數Bayou數據收集都包含無法解決的沖突的錯誤日志。但是,此類約定不在Bayou存儲系統的域中,可能會因應用程序而異。

當檢測到沖突並且在處理沖突的過程中,Bayou依然對外提供數據的可訪問性。

第4章 副本的一致性

Bayou系統保證通過反熵會話接收所有寫操作,並且兩個擁有相同寫操作集合的服務器將具有相同的數據內容。但是,bayou不強制限制寫傳播延遲。即,bayou系統僅能夠保證最終一致性。bayou保證所有的write操作將以定義好的順序執行,且每次執行的效果是相同的,並且沖突檢測和合並過程是確定的,以使對沖突的檢測和解決的行為是一致的。

這里的內容核心是定義了寫入操作的兩種狀態:提交(committed)和臨時(tentative)。

對於所有不再被重做的寫入操作稱之為穩定(stability)。處於提交狀態的寫是穩定的。

4.1臨時寫

bayou的兩個重要特性保證了最終一致性:

  1. 在所有服務器上,寫操作都以相同的、定義良好的順序執行;
  2. 沖突檢測和合並過程是確定的,服務器將以同樣的方式解決相同的沖突。

當Bayou服務器從客戶端接受寫入時最初被認為是試探性的。試探性寫入根據其接受服務器分配給它們的時間戳進行排序。最終,通過后文描述的提交過程提交每個寫入。已提交寫的順序是根據它們提交的時間和在任何臨時寫之前。

對於臨時寫,唯一的要求是在同一個服務器上被賦予單調遞增的時間戳。這樣通過<timestamp, WriteID>對就能對同一個服務器上的所有寫操作進行排序。在不同的服務器之間沒有要求對時鍾進行同步(實際上在不穩定的移動式網絡中也無法實現這一要求)。但是需要保持服務器之間的時鍾需要接近。Bayou服務器維護了一個邏輯時鍾,該邏輯時鍾通常與它的實時系統進行同步。為了保證因果順序,不同的服務器需要在反熵會話中對邏輯時鍾進行修正。

由於服務器的本地寫入操作已經執行,在通過反熵會話接收到其他服務器的寫入操作之后,需要對先前的寫入操作進行撤銷操作,並與傳來的寫入操作合並以獲取一個新的寫入操作序列,並依據新的全序序列對寫入操作進行重做。

Bayou通過限制合並過程只依賴於服務器當前的數據內容和合並過程本身提供的數據,確保在每個服務器上獨立執行的合並過程產生一致的更新。特別是,合並過程不能訪問時變的或特定於服務器的"環境"信息,如當前系統時鍾或服務器名稱。而且,由於超出資源使用限制而失敗的合並過程必須確定地失敗。這意味着所有服務器必須在分配給合並過程的CPU和內存資源上設置統一的邊界,並且必須在執行期間一致地執行這些邊界。一旦滿足了這些條件,兩個以相同副本開始的服務器將在執行Write后以相同副本結束。

4.2寫穩定和提交

一個寫入操作被稱之為是穩定(stable)的,當且僅當該服務器上記錄該寫入操作的log被固定下來之后。因此臨時寫入操作是不穩定的,因為其log還沒有固定。因為其他服務器可能具有該寫入操作之前的寫入操作,導致該寫入操作需要被重做。

應用程序則引入了confirmation和commitment的概念來對應bayou系統的寫穩定的概念。bayou提供了一套API以便於應用程序缺某個寫入操作是否是穩定的。

判斷寫操作是否穩定的方法如下:

  1. 每個服務器在反熵期間不僅傳送寫入操作集合,還傳送當前邏輯時鍾的值通過適當假設寫操作的傳播順序,服務器可以在時間戳低於所有服務器時鍾的情況下確定寫操作是穩定的。這種方法的主要缺點是,保持斷開連接的服務器可能會阻止"寫"的穩定,這可能導致服務器重新連接時回滾大量的"寫";
  2. 為了加快更新的速度,在一個與某些服務器通信可能無法延長時間的環境中,Bayou系統使用了一個提交過程。也就是說,當一個Write被顯式提交時,它就會變得穩定,事實上,在Bayou系統中,我們通常會交替使用術語"穩定"和"提交"。已提交的寫(按提交順序)放在每個服務器的寫日志中任何暫定的寫(Write)之前。這一點,再加上Bayou的反熵協議,確保服務器按照提交的順序了解提交的寫操作,從而提供了穩定性。

4.3 小結

bayou采取主服務器方案。這個方案要求指定某個server作為主服務器。在反熵過程中,主server將指定哪些寫入是committed,以及它們該以什么樣的順序執行這些寫入操作,並將這些信息傳遞給其他服務器。每個復制的數據集都可以指定不同的server作為主服務器。

bayou只是盡可能保證寫入操作的提交是根據臨時寫順序的時間戳進行排序的,但是並不保證這一點。

第5章 存儲系統實現問題

bayou設計對底層存儲系統有幾點要求:

  • 高效的日志記錄
  • 高效的撤銷/重做
  • 對committed和tentative數據提供不同的視圖
  • 支持服務器間的反熵操作

實現的三個組件:

  • 寫入日志

  • 元組存儲
    執行寫入操作和響應讀取請求的數據庫。運行在內存的關系型數據庫。

  • 撤銷日志

image_58

5.1 元組存儲

對外提供了兩個視圖,committed和full。臨時寫的效果反映在full視圖,committed寫的效果體現在committed視圖和full視圖。一個臨時刪除的操作可能會導致一個元組出現在committed視圖但是full視圖則不存在了。

元組數據庫使用2bit來標記某個元組是屬於full視圖還是committed視圖。這樣可以減少存儲空間(因為full視圖和committed視圖的數據是高度重合的),同時也使得對元組數據在full和committed視圖之間的轉換提供了方便,另外也便於查詢操作。

為了支持反熵操作,維護了兩個時間戳向量:C向量和F向量。

C向量表示最后一個committed Write執行完畢后的元組存儲的時間戳,F向量表示writelog中最后一個臨時寫執行完畢后的元組存儲的時間戳。用於指明哪些寫操作需要在反熵中被傳遞。

為了防止在反熵期間重復接收相同的寫操作,服務器維護了一個時間戳向量O向量(ommitted vector),每個服務器都存儲從指定服務器接收到的最新的寫操作的時間戳。

5.2 崩潰恢復

處於恢復的目的,完整的write log和tuple store的檢查點都維護在外存上。undo log則只維護在內存中。

第6章 訪問控制

授權粒度:一個數據集合。

權限:讀權限、寫權限、server權限(即創建一個新的數據集合副本)

每個用戶都擁有一個公私鑰對和一組訪問控制證書。在啟動時,用戶從相應的用戶獲取密鑰和證書。

Bayou使用三種證書來控制授予、委派和撤銷對數據集的訪問權:

  • AC[PU, P, D] 對擁有公鑰PU的用戶在數據集D上授予P(read/writ/server)權限;
  • D[PU, C, PY] 公鑰為PY的用戶使用相應的證書C將自己的權限也同樣地委派給公鑰為PU的用戶
  • R[C, PY] 公鑰為PY的用戶撤銷所有通過C證書獲取權限的用戶的權限

第7章 Bayou的特點

  • 沖突檢測和解決需要引用程序參與
  • 沖突檢測與應用相關
  • 每個write操作都包括一個合並過程,一旦寫沖突則執行合並過程
  • 局部和多對象更新。Bayou的Write操作可以自動地對一個或多個數據對象執行插入、部分修改和刪除操作
  • 臨時寫和穩定寫
  • 安全。有完整的身份驗證和訪問控制機制

第8章 思考

Bayou_Write的原子性問題

在前文對Bayou_Write的偽代碼描述中,我們可以看到,在執行寫操作之前會先進行沖突檢查,如果檢查到沖突,那么就需要執行合並過程解決沖突,最后再執行寫操作。這是一個非常復雜的過程,如果Bayou_Write本身不提供原子性,那么很容易導致寫寫沖突。即,當檢查沖突並解決沖突之后,由於進程切換,另一個進程對同一個數據進行了更改,這樣在切換回原來的進程之后,這個進程認為是不存在沖突的(因為已經解決了),但是實際上已經發生了沖突。這只是其中的一種情況,更多情況請讀者自行思考。因此考慮Bayou_Write的原子性是很有必要的。

如何設置主服務器

這個問題比較復雜,也是一個共識問題。這已經超出了本文討論范圍。

第9章 參考文獻


  1. TERRY D B, THEIMER M M, PETERSEN K, 等. Managing Update Conflicts in Bayou, a Weakly Connected Replicated Storage System[J]. [日期不詳]: 12. . ↩︎


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM