分佈式存儲系統 知識體系

最近看完了楊傳輝老師寫的《大規模分佈式存儲系統》一書,發現裏面不少知識點和以前看的《大型網站系統與Java中間件》有不少相通之處,也漸漸加 深了我對分佈式技術的興趣。但無奈分佈式涵蓋範圍太廣了,分佈式存儲、分佈式計算、CAP理論、Paxos算法、什麼GFS、Hadoop、 Dynamo、BigTable、Spanner等等,不下點功夫還真不能理順它們之間的內在關係。因此結合兩書以及一些優秀博文,總結了分佈式存儲的知 識體系,爲之後打下基礎而努力。因爲初入泥潭,必然有些理解不當的地方,如有大神路過還望不吝指教。html

本文更像是讀書筆記,是對知識點的一個梳理,無奈越寫越多,部分知識只能點到爲止,具體內容能夠查看原書或維基百科。算法

單機存儲引擎

哈希

哈 希存儲引擎是哈希表的持久化實現,支持增、刪、改,以及隨機讀取操做,但不支持順序掃描,對應的存儲系統爲鍵值(Key-Value)存儲系統,如 Bitcask。它僅支持追加操做,刪除也只是經過標識 value 爲特殊值,經過按期合併(Compaction)實現垃圾回收。sql

B 樹

B 樹存儲引擎是 B 樹的持久化實現,不只支持單條記錄的增、刪、讀、改操做,還支持順序掃描,對應的存儲系統是關係數據庫。關係數據庫中經過索引訪問數據,在 Mysql InnoDB 中,有一個稱爲彙集索引的東西,行的數據存於其中,組織成 B+ 樹的結構。更多 B 系樹的內容能夠參考 這裏數據庫

LSM 樹

LSM 樹(Log Structure Merge Tree)存儲引擎採用批量轉儲技術來避免磁盤隨機寫入。其思想很樸素,就是將對數據的修改增量保持在內存中,達到指定的大小限制後將這些修改操做批量寫 入磁盤。它普遍應用於互聯網的後臺存儲系統, 例如 Google BigTable、 以及 Facebook 開源的 Cassandra系統。緩存

分佈式存儲的出現

單機存儲隨着業務的增加會遇到性能單點故障問題。一般有兩種解決方案:服務器

  1. 數據分佈:就是把數據分塊存在不一樣的服務器上(分庫分表)。
  2. 數據複製:讓全部的服務器都有相同的數據,提供至關的服務。

這兩種方法都能解決性能上的問題,通常結合使用。而對於數據丟失的問題,咱們只能經過第二種方法來完成——數據的冗餘存儲。可是加入更多的機器,會 致使事情變得複雜起來,尤爲是分佈式事務處理,也就是多臺服務器之間的數據如何保持一致性,由於原先單機的 ACID 特性在分佈式環境下都用不了了。網絡

數據分佈

數據分佈主要有兩種方式:一種是哈希分佈,如一致性哈希(Dynamo);另外一種是順序分佈(BigTable)。考慮因素包括讀寫場景, 即隨機仍是順序, 包括如何保證負載均衡從而提升性能等數據結構

傳統的哈希分佈算法簡單的將哈希值與服務器個數作除法取模映射。可是當服務器上下線時,數據的從新分佈會帶來大量的數據遷移。架構

所以有了 一致性哈希算法 。算法思想以下 :給系統中每一個節點分配一個隨機 token,這些 token 構成一個哈希環。執行數據存放操做時,先計算 Key(主鍵)的哈希值,而後存放到順時針方向第一個大於或者等於該哈希值的 token 所在的節點。一致性哈希的優勢在於節點加入 / 刪除時只會影響到在哈希環中相鄰的節點,而對其餘節點沒影響。增長節點後能很大程度上避免了數據遷移。爲了考慮負載均衡,通常還會引入虛擬節點的技術,即 一個物理節點會對應着多個虛擬節點(如 Dynamo)。併發

數據複製

複製協議有兩種:強同步複製異步複製。 區別在於用戶的寫請求是否須要同步到備副本才能夠返回成功。

一致性和可用性是矛盾的。強同步複製協議保證主備副本之間的一致性,可是當備副本出現故障時會影響系統可用性。異步複製協議的可用性較好,可是一致性得不到保障,主副本出現故障時還有數據丟失的可能。

這兩種協議都是將主副本的數據以某種形式(多爲操做日誌)發送到其餘副本,這種複製協議稱爲基於主副本的複製協議。固然還有基於多個存儲節點的複製協議。好比下面會介紹的 Dynamo 系統的 NWR 複製協議。

故障檢測

設計分佈式系統的前提就是假定服務器時刻肯能發生故障。故障檢測主要有心跳和租約兩種機制。

  • 心跳:假設總控機 A 須要確認工做機 B 是否發生故障,那麼總控機 A 每隔一段時間,好比 1 秒,向工做機 B 發送一個心跳包。不足之處是若 A 到 B 網絡發生故障,則不能肯定是不是 B 再也不提供服務。
  • 租約:租約機制就是帶有超時時間的一種受權。假設機器 A 須要檢測機器 B 是否發生故障,機器 A 能夠給機器 B 發放租約,機器 B 持有的租約在有效期內才容許提供服務,不然主動中止服務。機器 B 的租約快要到期的時候向機器 A 從新申請租約。租約機制能夠解決上述心跳問題的不足。

一致性模型

提及數據一致性,簡單說有三種類型(細分會有不少,此處不展開):

  1. 弱一致性(Weak):當你寫入一個新值後,讀操做在各個數據副本上不保證能讀出最新值。好比:某些cache系統,網絡遊戲其它玩家的數據和你沒什麼關係。
  2. 最終一致性(Eventually):Eventually 是 Weak 的一種特殊狀況。當你寫入一個新值後,有可能讀不出來,但在某個時間窗口以後保證最終能讀出來。好比:DNS,電子郵件、Amazon S3,Google搜索引擎這樣的系統。
  3. 強一致性(Strong):新的數據一旦寫入,在任意副本任意時刻都能讀到新值。好比:文件系統,RDBMS,Azure Table都是強一致性的。

從這三種一致型的模型上來講,咱們能夠看到,Weak 和 Eventually 通常來講是異步冗餘的,而Strong通常來講是同步冗餘的,異步的一般意味着更好的性能,但也意味着更復雜的狀態控制。同步意味着簡單,但也意味着性能降低。

分佈式事務

事務的支持對於業務是很是重要的特性,數據庫在單機下的 ACID 事務特性是比較到位的,而一旦進行分庫分表後就要面對一致性和可用性的問題了,這就是分佈式事務了。

CAP 原理

在分佈式環境下須要考慮數據的一致性和性能的問題,咱們要了解下 CAP 理論

  • 一致性:全部節點在同一時間具備相同的數據。
  • 可用性:保證每一個請求無論成功或者失敗都有響應。我理解的是系統的性能。
  • 分區容忍性:系統中任意信息的丟失或失敗不會影響系統的繼續運做。我理解的是系統的抗故障能力。

在分佈式系統中,對於這三者不能同時知足。這就是 CAP 理論。

簡單地說就是:
1)要想讓數據避免單點故障,就得寫多份數據。
2)寫多份的問題會致使數據一致性的問題。
3)數據一致性的問題又會引起性能問題

NWR 模型

NWR 是一種在分佈式存儲系統中用於控制一致性級別的策略,應用於 Amazon Dynamo。NWR 模型將 CAP 的選擇權交給了用戶,由用戶本身選擇 CAP 中的哪兩個。其中,N 表明 N 個備份,W 表明至少寫 W 份才認爲成功,R 表明至少要讀 R 份才認爲成功。

  • 若是 W+R>N ,是能夠保證強一致性的。由於 W+R > N, 因此 R > N-W,什麼意思呢?就是讀取的份數必需要大於未成功寫的份數,這樣至少能讀到一份最新值。
  • 若是 W+R<=N,則可以保證最終一致性。
  • 若是咱們要高可寫的環境,咱們能夠配置 W=1 R=N。這個時候只要寫任何節點成功就認爲成功,可是讀的時候必須從全部的節點都讀出數據。
  • 若是咱們要求讀的高效率,咱們能夠配置 W=N R=1。這個時候任何一個節點讀成功就認爲成功,可是寫的時候必須寫全部三個節點成功才認爲成功。

兩階段提交

英文 Two Phase Commit,也叫 2PC。兩階段提交常常用於分佈式事務,是強一致性算法。簡要的說就是分兩階段:

第一階段,主控節點(協調者)詢問全部節點(參與者)是否能夠提交操做,參與者迴應 yes or no。
第二階段,協調者根據收到的響 應,若是全部參與者都回應 yes,則向全部參與者發送「正式提交」的命令。參與者完成後恢復「完成」消息,協調者收集齊各節點的迴應後結束這個 Global Transaction。若是有一個拒絕則給全部參與者發送「回滾操做」。參與者回滾成功後迴應「回滾完成」,協調者收集各結點的「回滾」迴應後,取消這 個 Global Transaction。

2PC說白了就是第一階段作 Vote,第二階段作決定的一個算法,相對於單庫事務來講就是在提交以前多了準備的階段。可是也存在着問題,其中一個是同步阻塞操做,這個事情必然會很是 大地影響性能。另外一個主要的問題是在TimeOut上。所以出現了 3PC,主要是將提交過程分爲兩步,更多描述見 Wikipedia

Paxos 算法

Google Chubby 的做者 Mike Burrows 說過,「世上只有一種一致性算法,那就是 Paxos」,全部其餘一致性算法都是Paxos算法的殘次版本。

Paxos是一個分佈式選舉算法, 最大的用途就是保持多個節點數據的一致性。看了很久的 Paxos 算法仍是有些迷糊,這裏就不給出具體算法了。感興趣的能夠參看 WikiPedia 以及裏面給出的示例。

實際上對於通常的開發人員,咱們並不須要瞭解 Paxos 全部細節及如何實現,只須要知道 Paxos 是一個分佈式選舉算法就夠了。當咱們之後遇到類似的問題,知道有這樣一個技術,能夠正確及優雅地解決技術架構上一些難題就夠了。

小結

Paxos 協議和 2PC 協議在分佈式系統中所起的做用並不相同。Paxos 協議用於保證同一個數據分片的多個副本之間的數據一致性。當這些副本分佈到不一樣的數據中心時,這個需求尤爲強烈。2PC 協議用於保證屬於多個數據分片上的操做的原子性。這些數據分片可能分佈在不一樣的服務器上,2PC 協議保證多臺服務器上的操做要麼所有成功,要麼所有失敗。可見 Paxos 的學術地位不通常。

Paxos 協議有兩種用法:一種用法是用它來實現全局的鎖服務或者命名和配置服務,例如 Google Chubby 以及 Apache Zookeeper 還有全局ID。另一種用法是用它來將用戶數據複製到多個數據中心,例如 Google Megastore 以及 Google Spanner。

2PC 協議最大的缺陷在於沒法處理協調者宕機問題。若是協調者宕機,那麼,2PC協議中的每一個參與者可能都不知道事務應該提交仍是回滾,整個協議被阻塞,執行過 程中申請的資源都沒法釋放。所以,常見的作法是將 2PC 和 Paxos 協議結合起來,經過2PC 保證多個數據分片上的操做的原子性,經過 Paxos 協議實現同一個數據分片的多個副本之間的一致性。另外,經過 Paxos 協議解決 2PC 協議中協調者宕機問題。當 2PC協議中的協調者出現故障時,經過 Paxos 協議選舉出新的協調者繼續提供服務。

下圖是幾種策略原理的比較,來源於:Google App Engine的 co-founder Ryan Barrett在2009年的google i/o上的演講《Transaction Across DataCenter》(視頻

圖中 M/S 是 Master-Slave) 結構,實現簡單,可是存在單點故障和數據丟失的問題。M/M 即 Multi-Master,解決了單點故障可是一致性的實現較複雜且存在衝突合併的問題(Vector Clock解決)。從上圖咱們能夠看到,咱們基本上來講不可讓全部的項都綠起來,也就是以前說到的著名的CAP理論:一致性,可用性,分區容忍性,你只可能要其中的兩個。

分佈式系統分類

分佈式文件系統

分佈式文件系統用於存儲 Blob 對象,典型的系統有 Facebook Haystack 以及 Taobao File System(TFS)。分佈式文件系統是分佈式的基石,一般做爲上層系統的底層存儲。

整體上看,分佈式文件系統存儲三種類型的數據 :Blob 對象、定長塊以及大文件。在系統實現層面,分佈式文件系統內部按照數據塊(chunk)來組織數據,每一個 chunk 的大小大體相同,每一個 chunk 能夠包含多個 Blob 對象或者定長塊,一個大文件也能夠拆分爲多個 chunk 。

分佈式鍵值系統

分佈式鍵值系統用於存儲關係簡單的半結構化數據,它只提供基於主鍵的 CRUD(Create/Read/Update/Delete)功能。

典型的系統有 Amazon Dynamo 以及 Taobao Tair。從數據結構的角度看,分佈式鍵值系統與傳統的哈希表比較相似,不一樣的是,分佈式鍵值系統支持將數據分佈到集羣中的多個存儲節點。分佈式鍵值系統 是分佈式表格系統的一種簡化實現,通常用做緩存,好比淘寶 Tair 以及 Memcache。一致性哈希是分佈式鍵值系統中經常使用的數據分佈技術。

分佈式表格系統

分佈式表格系統用於存儲關係較爲複雜的半結構化數據。分佈式表格系統以表格爲單位組織數據,每一個表格包括不少行,經過主鍵標識一行,支持根據主鍵的 CRUD 功能以及範圍查找功能。

典型的系統包括 Google Bigtable 以及 Megastore,Microsoft Azure Table Storage,Amazon DynamoDB 等。在分佈式表格系統中,同一個表格的多個數據行也不要求包含相同類型的列,適合半結構化數據。

分佈式數據庫

分佈式數據庫通常是從單機關係數據庫擴展而來,用於存儲結構化數據。分佈式數據庫採用二維表格組織數據,提供 SQL 關係查詢語言,支持多表關聯,嵌套子查詢等複雜操做,並提供數據庫事務以及併發控制。

典型的系統包括 MySQL 數據庫分片(MySQL Sharding)集羣,Amazon RDS 以及Microsoft SQL Azure。分佈式數據庫支持的功能最爲豐富,符合用戶使用習慣,但可擴展性每每受到限制。固然,這一點並非絕對的。Google Spanner 的擴展性就達到了全球級,它不只支持豐富的關係數據庫功能,還能擴展到多個數據中心的成千上萬臺機器。除此以外,阿里巴巴 OceanBase 也是一個支持自動擴展的分佈式關係數據庫。

摘錄

書中有不少對於分佈式的觀點對我啓發很大,將之引用以下。

    • 「Google的分佈式存儲系統一步步地從 Bigtable 到 Megastore,再到 Spanner,這也驗證了分佈式技術和傳統關係數據庫技術融合的必然性,即底層經過分佈式技術實現可擴展性,上層經過關係數據庫的模型和接口將系統的功 能暴露給用戶。」 OceanBase 正是看準了這兩種技術融合的必然性,才走向了可擴展的關係數據庫道路。   
    • 「簡單就是美。系統開發過程當中,若是某個方案很複雜,通常是實踐者沒有想清楚。」。關於這一點其實很早就據說過,就像貫穿UNIX哲學的 KISS原則(Keep It Simple,Stupid),而做者經過開發複雜的分佈式存儲系統過程當中得出這麼寶貴經驗,是「簡單就是美」最好的註解。

    • 中心化 VS 去中心。「主流的分佈式系統通常都帶有中心節點,這樣可以簡化設計,並且中心節點只維護少許元數據,通常不會成爲性能瓶頸。在實踐中 Dynamo 及其開源實現 Cassandra 受到的關注逐漸減小,去中心的設計短時間內難以成爲主流。」

相關文章
相關標籤/搜索