與單機環境下編程相比,分佈式環境下的編程有兩點不一樣:算法
數據的種類大體能夠分爲三類:數據庫
根據儲存數據種類的不一樣,能夠將儲存系統分爲如下幾類:編程
傳統的數據中心網絡拓撲爲三層結構,該網絡拓撲下,同一接入層下服務器之間帶寬相同,不一樣接入層的服務器帶寬會出現不一致的狀況,所以,設計系統時須要考慮服務器是否在一個機架內。緩存
爲了減小系統對網絡拓撲結構的依賴,能夠採用三級 CLOS 網絡,使得任何兩臺服務器之間的帶寬都相同。服務器
Bitcask 是基於哈希表結構的鍵值存儲系統,僅支持追加操做。內存中採用的是基於哈希表的索引,哈希表結構中的每一項包含文件編號(file_id),value 在文件中的位置(value_pos),value 長度(value_sz)。經過讀取 file_id 對應的文件,從 value_pos 開始的 value_sz 個字節,就可獲得 value 值。網絡
葉子節點保存每行的完整數據,非葉子節點保存索引信息。數據庫查詢時從根節點開始二分查找到葉子節點,每次讀取節點時,若是節點不在內存中,須要從磁盤中讀取並緩存。負載均衡
緩衝區管理器會決定哪些頁面淘汰,緩衝區的替換策略有如下兩種:異步
LSM 樹就是將對數據的修改增量保持在內存中,達到指定大小後將這些修改操做批量寫入磁盤,讀取時須要合併磁盤中的歷史數據和內存中最近的修改操做。分佈式
LevelDB 存儲引擎包括:內存中的 MemTable 和不可變的 MemTable。寫入記錄時,LevelDB 會先將修改操做寫入操做日誌,以後再將修改操做應用到 MemTable,這樣就完成了寫入操做。MemTable 的大小達到上限值後,LevelDB 會將原先的 MemTable 變成不可變 MemTable,並從新生成新的MemTable,以後的修改操做記錄在新的 MemTable 中。同時 LevelDB 後臺線程會將不可變 MemTable 的數據轉儲到磁盤。函數
分佈式系統通常使用操做日誌技術來實現故障恢復。操做日誌能夠分爲回滾日誌(undo log),重作日誌(redo log)。回滾日誌記錄的是事務修改前的狀態,重作日誌記錄的是事務修改以後的狀態。
爲了數據庫數據的一致性,數據庫操做須要持久化到磁盤,若是每次操做都更新磁盤上的數據,系統性能會較差。操做日誌上面記錄的就是每一個數據庫操做,並在內存中執行這些操做,內存中的數據定時刷新到磁盤,就能夠實現隨機寫請求轉化爲順序寫請求。
使用 REDO 日誌進行故障恢復,必須確保,在修改內存中的數據以前,把這一修改相關的操做日誌刷新到磁盤上。這麼作的緣由在於,假設是先修改內存數據,若是在完成內存修改和寫入日誌之間發生故障,那麼最近的修改操做沒有辦法經過 REDO 日誌恢復,用戶可能讀取到修改後的結果,出現不一致的狀況。
以前說過,數據庫操做須要先寫入操做日誌,可是若是每次操做都當即將操做日誌刷人磁盤,系統性能會下降。所以能夠先將 REDO 日誌儲存在緩衝區,按期刷入磁盤。但這樣作,可能會丟失最後一部分數據庫操做。
當內存不足,或者 REDO 日誌的大小達到上限時,須要將內存中修改後的數據刷新到磁盤上,這種技術就是 checkpoint(檢查點)技術。同時系統會加入 checkpoint 時刻,之後的故障恢復只須要回放 checkpoint 時刻以後的 REDO 日誌。
在分佈式系統中,若是一個節點發起 RPC 調用,RPC 執行結果有三種:「成功」,「失敗」,「超時」。當出現超時狀態時,不能簡單的認爲 RPC 操做失敗,只能經過不斷讀取以前操做的狀態來驗證 RPC 操做是否成功。固然,能夠將系統設計爲冪等性。
保證多個副本之間的一致性是分佈式系統的核心。例若有 A,B,C 同時操做存儲系統,能夠將一致性大體分別三種:
分佈式系統不一樣於傳統的單機系統,分佈式系統可以將數據分佈到多個節點,在多個節點間實現負載均衡。如下介紹的是數據分佈的兩種方式。
哈希分佈就是根據數據的某一特徵計算哈希值,哈希值與服務器有映射關係,以此實現數據的分佈。哈希分佈的優劣取決於散列函數的特徵,容易出現「數據傾斜」的問題。並且,當有服務器上線或者下線時,哈希映射會被打亂,會帶來大量的數據遷移。
一致性哈希能夠避免集羣擴容形成的大量數據遷移問題。其思想是:系統中的每一個節點都分配一個 token,這些 token 構成哈希環。儲存數據時,先計算數據的哈希值,而後存放到順時針第一個大於或者等於該哈希值的節點。這樣在增長、刪除節點時,只會影響到哈希環中相鄰的節點。一致性哈希能夠採用虛擬節點的發放來實現負載均衡。
哈希分佈實現數據分佈時,不能支持順序掃描。順序分佈能夠提供連續的範圍掃描,通常作法是將大表順序分爲連續的範圍,每一個範圍一個子表。Bigtable 系統將索引分爲兩級,Root 表和元數據 Meta 表,由 Meta 表維護 User 表的位置信息, Root 表維護 Meta 表的位置信息。
在分佈式系統中,同一份數據有多個副本,其中一個副本爲主副本,其餘爲備副本。複製時,由主副本將數據複製到備份副本。複製協議能夠分爲強同步複製和異步複製。
強同步複製要求主備成功後才能夠返回成功,能夠保證強一致性,可是,複製時是阻塞寫操做,系統可用性較差。
異步複製就是主副本不須要等待備副本的迴應,只須要本地修改爲功就能夠返回成功。
上述兩種複製協議都是主副本將數據發送給其餘副本,當主副本出現故障時,須要選擇新的主副本。經典的選舉協議爲 Paxos 協議。
CAP 理論就是:一致性(Consistency),可用性(Availability),分區可容忍性(Tolerance of network Partition)三者不能同時知足。
分區可容忍性指的是在機器故障、網站故障等異常狀況下仍然知足一致性和可用性。
設計存儲系統時須要在一致性和可用性之間權衡。若是採用強同步複製,保證系統的一致性,當主備副本之間出現故障時,寫操做被阻塞,系統的可用性將沒法知足。若是採用異步複製,保證了可用性,但沒法作到一致性。
Oracle 數據庫的 DataGuard 複製組件有三種模式,能夠借鑑:
故障檢測可使用心跳的方式來作,但並不能保證機器必定出現了故障,多是機器 A 和機器 B 之間的網絡發生問題。
一般使用租約機制來進行故障檢測。租約機制就是:機器 A 向 機器 B 發放租約,機器 B 在持有租約的有效期內才容許提供服務,不然主動中止服務,機器 B 能夠再租約快要到期的時候向機器 A 從新申請租約。
總控節點檢測到工做機器出現故障時,須要將服務遷移到其餘工做機節點。總控節點自己可有可能出現故障,也須要將自身狀態實行同步到備機。
分佈式存儲系統的總控節點只須要維護數據的位置信息,一般不會成爲瓶頸。若是成爲瓶頸,能夠採用兩級結構:
數據庫擴容的手段有:
傳統的數據庫爲同構系統,在擴容上不夠靈活。同一組內的節點存儲相同的數據,在增長副本時須要遷移的數據量太大。
、
異構系統將數據劃分爲不少大小接近的分片,每一個分片的多個副本能夠分佈 到集羣中的任何一個存儲節點。若是某個節點發生故障,原有的服務將由整個集羣而不 是某幾個固定的存儲節點來恢復。如圖3-9所示,系統中有五個分片(A, B, C, D, E),每一個分片包含三個副本, 如分片A的三個副本分別爲Al, A2以及A3。假設節點1發生永久性故障,那麼能夠 從剩餘的節點中任意選擇健康的節點來增長A, B以及E的副本。因爲整個集羣都參與 到節點1的故障恢復過程,故障恢復時間很短,並且集羣規模越大,優點就會越明顯。
兩階段提交協議(2PC)用來保證跨節點操做的原子性。該協議中,將系統節點分爲:協調者和事務參與者。正常執行過程以下:
兩階段提交協議可能面臨的故障:
兩階段提交協議是阻塞協議,執行期間要鎖住其餘更新,且不能容錯。大多數分佈式存儲系統都對之避而遠之。
Paxos 協議用來解決多個節點之間的一致性問題。當主節點出現故障時,Paxos 協議能夠在多個備節點中選舉出惟一的主節點。
Paxos 協議的兩種用法:
paxos 協議怎麼作的???待填坑!!!
2PC 能夠和 Paxos 協議結合起來,經過 2PC 保證多個數據分片上的操做的原子性,經過 Paxos 協議實現同一數據分片的多個副本之間的一致性。另外,經過 Paxos 協議解決 2PC 協議中協調者出現故障的問題。當 2PC 協議中的協調者出現故障時,經過 Paxos 協議選舉出新的協調者繼續提供服務。