Cassandra - 一個分散的結構化儲存系統

lengyuhong發表於2010-11-04

Cassandra - 一個分散的結構化儲存系統

本文翻譯自Facebook員工在LADIS大會上釋出的論文.Cassandra – A Decentralized Structured Storage System
這篇論文中,兩位作者詳細介紹了Cassandra的系統架構,它的設計初衷,設計應用時使用到的相關技術,以及設計/實現/使用過程中得到的經驗教訓.

Cassandra – 一個分散的非結構化儲存系統
By Avinash Lakshman Facebook ,Prashant Malik Facebook; Translated By Jametong

概要

Cassandra是一個分散式的儲存系統,可用來管理分佈在大量廉價伺服器上的巨量結構化資料,並同時提供沒有單點故障的高可用服務.Cassandra的設計目的是執行在由幾百個節點(可能分佈在多個不同的資料中心)組成的基礎設施(infrastructure)上.當節點達到這個規模時,大大小小的元件出現故障就可能經常發生了.Cassandra在管理持久狀態時面臨這些故障,這種情況也驅動軟體系統的可靠性(reliability)與可伸縮性(scalability)會依賴於Cassandra的服務.雖然大部分情況,Cassandra看上去像一個資料庫系統, 也與資料庫系統共享大量的設計與實現手段,但是Cassandra並不支援完整的關係資料模型;相反,它提供了一個簡單資料模型的客戶端,支援對資料佈局與資料格式的動態控制.我們設計Cassandra的初衷是,可以執行在廉價硬體上,並能在不犧牲讀效率的情況下實現高的寫吞吐量.

1. 導論

Facebook維護著世界上最大的社交網路平臺,利用分佈在世界各地的大量資料中心的成千上萬臺伺服器,為上億的使用者提供服務.Facebook平臺有嚴格的業務要求,包含效能、可靠性、效率以及高度的可伸縮性以支援平臺的持續增長.在一個包含成千上萬的元件的基礎設施上處理故障是我們的標準運作模式;在任何時候,隨時都可能出現相當數量的伺服器或網路元件故障.這樣,軟體系統在構建時就需要將故障當作一種常態而不是異常來處理.為了滿足上面描述的這些可靠性與可伸縮性,Facebook開發了Cassandra系統.
為了實現可伸縮性與可靠性,Cassandra組合了多項眾所周知的技術.我們設計Cassandra的最初目的是解決收件箱搜尋的儲存需要.在Facebook,這意味著這個系統需要能夠處理非常大的寫吞吐量,每天幾十億的寫請求,隨著使用者數的規模而增長.由於我們是通過在地理上分佈的資料中心對使用者進行服務的,因此支援跨越多個資料中心的資料複製對於降低搜尋延時就非常關鍵了.當我們在2008年6月釋出收件箱搜尋專案時,我們有1億的使用者,現在我們差不多有2.5億的使用者,Cassandra一直保持了其對業務的承諾.目前,Facebook內部已經有多個服務部署了Cassandra作為其後端儲存系統.
本文的結構如下.第2節討論相關研究,其中的部分研究對我們的設計有很大影響.第3節介紹詳細的資料模型.第4節簡要介紹客戶端API.第5節介紹系統設計以及Cassandra中應用到的分散式演算法.第6節介紹我們如何使用Cassandra部署Facebook平臺的一個應用.

2. 相關研究

對於為了效能、可用性與資料永續性對資料進行分佈,檔案系統與資料庫社群已經進行了廣泛的研究.與僅支援扁平名稱空間(namespace)的點對點(P2P)儲存系統相比,分散式檔案系統通常支援層次化(hierarchical)的名稱空間.與Ficus[14]與Coda[16]類似的系統都是通過犧牲一致性來複制檔案以實現高可用(high availability).通常使用特別的衝突解決(conflict resolution)程式來管理更新衝突(update conflict). Farsite[2]是一個沒有使用任何中心伺服器的分散式檔案系統. Farsite使用複製來實現高可用性與可伸縮性.Google檔案系統(GFS)[9]是另一個分散式檔案系統,用來儲存Google內部應用的各種狀態資料.GFS設計比較簡單,用一臺主伺服器儲存所有的後設資料(metadata),資料拆分成塊(chunk)儲存在多個塊伺服器(chunk server)上.不過,目前Google已經使用Chubby[3]抽象層為GFS的主伺服器做了容錯處理(fault tolerant).Bayou[18]是一個分散式的關聯式資料庫系統,它支援斷開操作(個人理解為網路斷開以後的操作)並提供最終的資料一致性(eventual data consistency).在這些系統中,Bayou、Coda與Ficus允許斷開操作,並且在遇到類似與網路斷開與停機時能夠做到自動復原.這些系統在衝突解決程式上存在差異.例如,Coda與Ficus執行系統級別的衝突解決,而Bayou允許應用級別的衝突解決.但所有這些都保證最終一致性(eventual consistency).與這些系統類似,即使在網路段開的時候,Dynamo[6]也允許進行讀寫操作,並使用不同的衝突解決機制(部分客戶端驅動)來解決更新衝突.傳統的基於複製的關聯式資料庫系統重點在保證複製資料的強一致性(strong consistency).雖然強一致性為應用寫程式提供了一個方便的程式設計模型,但是,這些系統在伸縮性與可用性方面卻受到了限制.因為這些系統提供強一致性的保證,所以在網路分開時,它們就無法進行處理.
Dynamo[6]是一個Amazon開發的儲存系統,Amazon用它來儲存檢索使用者的購物車.Dynamo利用基於Gossip的會員演算法來維護每個節點上所有其他節點的資訊.可以認為Dynamo是一個只支援一跳路由請求(one-hop request routing)的結構化覆蓋層(structured overlay).Dynamo使用一個向量時鐘(vector lock)概要來發現更新衝突,但偏愛客戶端的衝突解決機制.為了管理向量時間戳(vector timestamp),Dynamo中的寫操作同時也需要執行一次讀操作.在一個需要處理非常大的寫吞吐量的系統中,這可能會成為瓶頸. Bigtable[4]既提供了結構化也支援資料的分散式,不過它依賴於一個分散式的檔案系統來保證資料的持久化.

3. 資料模型

Cassandra中的表是一個按照主鍵索引的分散式多維圖.它的值是一個高度結構化的物件.表中的記錄鍵是一個沒有大小限制的字串,雖然它通常都只有16-36個位元組的長度.無論需要讀寫多少列,單一記錄鍵的每個副本的每次操作都是一個原子操作.多個列可以組合在一起形成一個稱為column family的列的集合,這一點與Bigtable[4]系統非常相似.Cassandra提供兩種型別的column family,簡單的column family與超級的column family.可以將超級column family想象成column family裡面嵌入column family.進一步,應用還可以指定超級column family或者簡單column family裡面的列的排序順序.系統允許按時間或者名稱對列進行排序.按照時間對列進行排序可以被類似於收件箱搜尋這樣的應用使用,因為它們的結果始終需要按照時間順序進行展示.column family中的每個列都需要通過規範column family : column來進行訪問,每個超級column family中的列都通過規範column family : super column : column來進行訪問.小節6.1給出了一個展示超級column family抽象能力的非常好的例子.通常,應用都會使用一個獨佔的Cassandra叢集,並將它們當作服務的一部分進行管理.雖然,Cassandra系統支援多表的概念,在部署時每個概要中都只能有一個表.

4. API

Cassandra的API由下面三種方法組成.

  • insert(table, key, rowMutation)
  • get(table, key, columnName)
  • delete(table, key, columnName) 列名可以是column family裡面的一個特定列,或column family,或超級column family,或超級列裡面的一個列

5. 系統架構
一個需要在生產環境運轉的儲存系統的架構是很複雜的.除了真實的資料持久化元件外,這個系統還需要包含以下特性;可伸縮性與強大負載均衡解決方案、會員與故障檢測、故障恢復、副本同步、超負荷處理、狀態轉移、併發與任務排程、請求編組、請求路由、系統監控與報警以及配置管理.詳細描述這裡的每一個解決方案超出了本論文的範圍,我們將集中介紹Cassandra使用的核心的分散式系統技術:分割槽、複製、會員、故障處理以及伸縮性.處理讀寫請求需要所有這些模組的協同處理.通常,一個鍵的請求可能被路由到Cassandra叢集的任何一個節點去處理.這個節點會確定這個特定的鍵的副本.對於寫操作來講,系統會將請求路由到副本上,並且等待仲裁數量的副本以確認寫操作完成.對於讀操作來講,基於客戶端要求的一致性保證,系統要麼將請求路由到最近的副本,要麼將請求路由到所有的副本並等待達到仲裁數量的響應.

5.1 分割槽.

增量擴充套件的能力是我們設計Cassandra時考慮的一個關鍵特性.它要求做到在叢集中的一組節點(Node)之間動態的對資料進行分割槽.Cassandra使用一致性雜湊(consistent hash[11])技術在整個叢集上對資料進行分割槽,但是使用一種保證順序(order preserving)的雜湊函式來實現.在一致性雜湊中,雜湊函式的輸出結果區間可以看作是一個封閉的圓形空間或者”環”(例如,最大的雜湊值迴繞到最小的雜湊值).為系統中的每個節點分配這個空間上的一個隨機值,代表它在這個環上的位置.每個資料項都會根據它的鍵被指派給一個節點,通過對這個資料項的鍵做雜湊計算,獲得它在環上的位置,然後按照順時針找到比它的位置大的第一個節點.這個節點就被認為是這個鍵的協調器.應用指定這個鍵,Cassandra利用它來對請求做路由.這樣,每個節點都會負責環上的一個區間-節點與它在環上的前一個節點(逆時針)之間的區間.一致性雜湊的主要優勢是增加或刪除節點只會影響到它的近鄰,其他的節點都不會受影響.基本的一致性雜湊演算法還面臨一些挑戰.首先,在環上隨機的為每個節點指定位置可能導致資料與負載的分佈不均衡.其次,基本的一致性演算法會抹殺節點之間效能的異質性(差異).解決這個問題一般有兩種方法:一種方法是在環上為節點指定多個位置(Dynamo採用的方法),另一種方法是分析環上的負載資訊,並移動負載較低的節點的位置以緩解負載過重的節點,引文[17]對此有詳細描述.Cassandra選擇了後者,因為使用它可以簡化設計與實現,並且可以讓負載均衡的選擇更加具有確定性.

5.2 複製

Cassandra使用複製來實現高可用性與永續性.每個資料項都會被複制到N臺主機,N是通過引數”per-instance”配置的複製因子.每個鍵(k)都被指派給一個協調節點(上一節介紹的).由協調節點負責複製落在這個節點範圍的資料項的複製.除了將本節點範圍內的資料儲存到本地外,協調器需要將這些鍵複製到環上的其他N-1個節點.關於如何複製資料,Cassandra為客戶端提供了多個選項.另外,Cassandra還提供了多種不同的複製策略,例如”機架不可知”(rack unaware)、”機架可知”(rack aware)(同一個資料中心內)與”資料中心可知”(data-center aware).應用選擇的複製策略決定了副本的數量.使用”機架可知”與”資料中心可知”複製策略時複製的演算法要稍微複雜一點.Cassandra使用一個稱為Zookeeper[13]的系統在這些節點中選擇一個引導者(leader).所有節點在加入叢集時都需要與此引導者聯絡,並由引導者告知它們負責哪個環上哪個範圍的副本,引導者還需保持協調一致的努力來保持不變,以確保沒有哪個節點負責環上的超過N-1個範圍.關於一個節點負責的範圍的後設資料(metadata)資訊都會在每個節點做本地快取,並在Zookeeper內做容錯處理,這樣當一個節點崩潰並返回的時候就可以知道它到底負責哪個範圍.借用Dynamo的措辭,我們認為負責一個給定範圍的節點是這個範圍的”優選清單”.

5.1節已經介紹了每個節點都知悉系統中的所有其他節點,以及它們各自負責的範圍.通過放寬5.2節介紹的仲裁數(quorum)的要求,即使在出現節點故障與網路分割槽的情況下,Cassandra也可以保證永續性.在斷電、冷卻故障、網路故障或自然災害時,資料中心也會發生故障.可以配置Cassandra使得每條記錄都被複制到多個不同的資料中心.實際上,可以這樣構建一個鍵的偏好列表,以實現鍵的儲存節點分佈在多個資料中心.這些資料中心都是通過高速網路進行互聯.即使整個資料中心出現故障,這種跨越多個資料中心的複製架構允許我們做到不當機.

5.3 會員

Cassandra中的叢集會員是基於Scuttlebutt[19]的,一個非常高效的反熵閒話(anti-entropy Gossip)機制. Scuttlebutt的突出的特點是它非常高效的CPU利用率以及非常高效的Gossip通道利用率.在Cassandra中,系統Gossip不止用來管理會員資訊,也用來傳輸其他系統相關的控制狀態.

5.3.1 故障檢測

故障檢測是這樣一種機制,通過它一個節點在本地就可以確定系統中的任一其他節點是活著還是死了.在Cassandra中,故障檢測還被用來避免在多個操作中與不可達節點的進行通訊.Cassandra使用的是Φ Accrual故障檢測器[8]的一個改進版本. Accrual故障檢測器的設計思路是,故障檢測模組並不是產生一個布林值來標記一個節點是活著還是死了.相反,故障檢測模組為每個被監控節點產生一個代表其懷疑級別的數值.此值被定義為Φ.其基本的思路是用Φ的值來表示一個範圍,可以動態對其進行調整以反映監控節點上的網路與負載情況.
Φ有以下幾種涵義:給定部分閾值Φ,並假定當Φ=1時我們就決定懷疑一個節點A,我們犯錯誤(例如,這個決定在將來可能由於心跳接收延遲而被證明是錯誤的)的概率為10%.Φ=2時出錯的概率大約為1%,Φ=3大約為0.1%,等等.系統中的每個節點都會維護一個滑動視窗,來表示叢集中其他節點的gossip資訊的到達間隔時間.確定了這些到達間隔時間的分佈後,就可以計算出Φ的值了.雖然原論文認為這個分佈近似於高斯分佈(Gaussian distribution),由於gossip通道的本性以及他對延時(latency)的影響,我們認為它與指數分佈(Exponential Distribution)更加相似.據我們所知,我們實現的Accrual故障檢測在基於Gossip的配置中還屬首創. Accrual故障檢測器在準確性與速度上表現都非常好, 它們也能很好的適應不同的網路環境或伺服器負載環境.

5.4 載入程式

當一個節點第一次啟動的時候,它會隨機的選擇一個令牌(token)作為它在環上的位置.為了容錯的需要,對映關係會被持久化到本地磁碟以及Zookeeper中.接著令牌資訊會被傳播到整個叢集.我們就是通過它來知道叢集中的所有節點以及它們在環上的位置的.通過它,任何一個節點都可以將一個鍵(key)的請求路由到叢集中的合適的節點.在引導過程中,當一個新的節點需要加入叢集時,它需要讀取它的配置檔案,配置檔案中包含叢集中的幾個聯絡點名單.我們將這些聯絡點稱為叢集的種子(seed).種子也可以來自一個類似於Zookeeper的配置服務(configuration service).
在Facebook的環境中,節點停機時間(由於故障或維護任務)通常都很短暫,但有時也會延長一段時間.故障可能有多種形式,如磁碟故障、CPU損壞等.節點停機很少不表示永遠離開(刪除節點),因此,不該導致分割槽指派的重新平衡或不可達副本的修復.類似地,手工錯誤可能會導致意外地啟動新的Cassandra節點.為了避免出現這種效果,所有訊息中都包含了每個Cassandra例項叢集名稱.如果配置中的手工錯誤導致一個節點嘗試加入一個錯誤的Cassandra例項,就可以根據叢集名稱來阻止它.由於上述原因,使用一種明確的機制來往Cassandra例項中新增或從中刪除節點或許更加合適.管理員使用命令列(command line)工具或者瀏覽器登陸到Cassandra的節點,提出一個會員變更(節點變更)來加入或離開叢集.

5.5 叢集的擴充套件

當有一個新節點加入系統時,它會被分配一個令牌,這樣就可以緩解負載過重的節點的負載.這樣導致的結果是,這個新的節點會分擔部分先前由其他節點負責的範圍.Cassandra的引導演算法可由系統中的任何其他節點通過命令列工具或Cassandra的網路儀表盤(web dashboard)來啟動.放棄這部分資料的節點通過核心到核心的拷貝技術將資料拷貝到新的節點.我們的運維經驗顯示,從單個節點傳輸的速率可以達到40MB/s.我們還在努力對它進行改善,通過讓多個副本來參與並行化引導傳輸,類似於Bittorrent技術.

5.6 本地持久化

Cassandra系統要依賴於本地檔案系統做資料的持久化.這些資料是以一種易於高效檢索的格式儲存在磁碟上.通常,一次寫操作會涉及提交日誌(Commit Log,為了資料耐用性與可恢復性)寫入,以及一次記憶體資料結構的更新.只有在寫入提交日誌成功返回後,才會執行記憶體資料結構的寫入操作.在每臺主機上,我們都單獨地分配了一塊磁碟存放提交日誌.由於提交日誌地所有寫入操作都是連續的(sequential),所以我們可以最大程度的利用磁碟吞吐量.當記憶體資料結構的大小(根據資料量大小與物件數量計算得出)超過一定的閾值,它就會將自身轉儲到磁碟.這個寫操作會機器配備大量的廉價磁碟的某一個上執行.所有到磁碟的寫操作都是順序寫.隨著時間的推移,磁碟上就會存在多個這樣的檔案,後臺會有一個合併程式(merge process)將這些檔案合併成一個檔案.這個程式與Bigtable系統中的壓縮排程(compact process)非常類似.
通常,一個讀操作在檢索磁碟檔案之前會先查詢這個記憶體資料結構.檢索磁碟檔案是按照先新後舊的方式進行的.當發生磁碟檢索時,我們可能需要檢視多個磁碟檔案.為了避免檢視不包含相應鍵(key)的檔案,我們使用了布隆過濾器(bloom filter),它對檔案中的鍵進行了彙總,它同時存在於每一個資料檔案中並常駐在記憶體中.當需要檢索某個鍵時,會先查閱此布隆過濾器以確認給定的檔案是否確實包含此鍵.column family中的一個鍵可以包含大量的列.當檢索的列距離鍵較遠時還需要利用一些特殊的索引.為了避免在磁碟上掃描每一列,我們維護了一份列索引來幫助我們直接定位到磁碟上的對應塊.由於指定鍵的列已經被序列化並寫出到磁碟,我們是按照每個塊(chunk)256K的範圍建立索引的.塊的範圍大小是可配置的,不過,我們發現256K的大小在我們的生產工作負載下運作良好.

5.7 實現細節

單臺機器上的Cassandra程式主要由以下模組組成:分割槽模組、叢集會員管理模組、故障檢測模組與儲存引擎模組.所有這些模組都依賴於一個事件驅動的底層模組,它是按照SEDA[20]架構設計的,將訊息處理管道與任務管道切分成了多個階段.所有這些模組都是完全利用Java實現.叢集會員模組與故障檢測模組都建立在使用非堵塞IO的網路層上.所有的系統控制資訊都依賴於基於UDP協議的訊息傳輸,而複製與請求路由等應用相關的訊息則依賴於TCP協議傳輸.請求路由模組的實現使用了一個固定的狀態機.當叢集的任一節點收到一個讀/寫請求時,狀態機都會在以下幾種狀態之間切換: (i)定位擁有這個鍵的資料的節點(ii)將請求路由到此節點並等待響應到達(iii)如果答覆沒有在配置的超時時間內到達,就將此請求置為失敗並返回給客戶端(iv)根據時間戳算出最新的答覆(v)為任何資料不是最新的副本的安排資料修復.出於論述起見,詳細的故障情況我們就不在此討論了.這個系統的複製模式可以配置為同步寫(synchronous write)也可以配置為非同步寫(asynchronous write).對於特定的需要高吞吐量的系統,我們會選擇依賴於非同步複製.這時,系統接收到的寫操作遠遠超過讀操作.對於使用同步的例子,在返回給使用者之前我們會等待達到仲裁的響應數量.
在任何日誌檔案系統中,都需要有一個機制來清理提交日誌項(commit log entry), 在Cassandra中,我們使用一種滾動的提交日誌,在一箇舊的提交日誌超過一個特定的可配置大小後,就推出一個新的提交日誌.在我們的生產環境中,我們發現128M的滾動提交日誌運作良好. 每個提交日誌都有一個頭資訊,基本上是一個大小固定的位向量,其大小通常超過一個系統可能處理的column family的個數.在我們的實現中,對於每個column family,我們都會生成一個記憶體資料結構以及一個資料檔案.每當一個特定的column family的記憶體資料結構轉儲到磁碟,我們都會在提交日誌中記錄它對應的位,說明這個column family已經被成功地持久化到磁碟.這表明這部分資訊已經提交了.每個提交日誌都有一份對應的位向量,這些位向量的資訊同時也在記憶體中進行維護.每當發生提交日誌滾動的時候,它的位向量,以及它之前滾動的提交日誌的位向量都會被檢查一下.如果確定所有的資料都已經被成功地持久化到磁碟,就刪除這些提交日誌.到提交日誌的寫操作可以是普通模式(normal mode)也可以是快速同步模式(fast sync mode).在快速同步模式下,到提交日誌的寫操作會被緩衝(buffered).這表明在機器崩潰時可能會出現潛在的資料丟失.在這種模式下,記憶體資料結構轉儲到磁碟也會被緩衝.傳統的資料庫通常都不會被設計用來處理特別高的寫入吞吐量.Cassandra將所有的寫入操作都轉換成順序寫操作以最大限度地利用磁碟的寫入吞吐量.由於轉儲到磁碟的檔案不再會被修改,從而在讀取它們的時候也不需要持有任何鎖.Cassandra的服務例項的讀寫操作實際上都是無鎖操作.所以,我們並不需要應付基於B-Tree的資料庫實現中存在的併發問題.
Cassandra系統通過主鍵來來索引所有資料.磁碟上的資料檔案被分解成一系列的塊.每個塊內最多包含128個鍵,並通過一個塊索引來區分.塊索引抓取塊內的鍵的相對偏移量以及其資料大小.當記憶體資料結構被轉儲到磁碟時,系統會為其生成一個索引,它的偏移量會被寫當作索引寫到磁碟上.記憶體中也會維護一份這個索引以提供快速訪問.一個典型的讀操作總是會先檢索記憶體資料結構.如果找到就將資料返回給應用程式,因為記憶體資料結構中包含任何鍵的最新資料.如果沒有找到,那麼我們就需要對所有磁碟資料檔案按照時間逆序來執行磁碟IO.由於總是尋求最新的資料,我們就先查閱最新的檔案,一旦找到資料就返回.隨著時間的推移,磁碟上的資料檔案數量會出現增加.我們會執行一個非常類似於Bigtable系統的壓縮排程,通過它將多個檔案壓縮成一個檔案.基本上是對很多排序好的資料檔案進行合併排序.系統總是會壓縮大小彼此接近的檔案,例如,永遠不會出現一個100GB的檔案與另一個小於50GB的檔案進行合併的情形.每隔一段時間,就會執行一個主壓縮程式來將所有相關的資料檔案壓縮成一個大檔案.這個壓縮排程是一個磁碟IO密集型的操作.需要對此做大量的優化以做到不影響後續的讀請求.

6. 實踐經驗

在設計、實現以及維護Cassandra的過程中,我們積累了不少有益的經驗,也獲得了許多經驗教訓.一個非常基本的經驗教訓是,在沒有理解應用的使用效果之前不要增加任何新特性.最成問題的情況不僅僅來自節點崩潰與網路分割槽.我們將在此分享幾個有趣的場景.

  • 在釋出收件箱搜尋應用之前,我們必須先為超過1億使用者的7TB的收件箱資料建立索引,接著將它們儲存到我們的MySQL[1]基礎結構中,然後再將它們載入到Cassandra系統中.整個處理過程涉及到在MySQL資料檔案上執行Map/Reduce[7]任務,為它們建立索引,並按照逆序索引的方式將它們儲存到Cassandra中.實際上,M/R程式是作為Cassandra的客戶端執行的.我們為M/R程式開放了後端通道,使它們可以按使用者彙總逆序索引,並將序列化後的資料傳輸給Cassandra例項,以節省序列化/反序列化的開銷.這樣,Cassandra例項的瓶頸就只剩下網路頻寬了.
  • 大部分應用都是隻需要每個鍵的每個副本的原子操作.不過,還是有部分應用需要交易支援,它的主要目的是維護輔助索引.大部分有著多年RDBMS相關開發經驗的開發人員都認為這個特性很有用.我們正在研究開放此類原子操作的機制.
  • 我們嘗試實現了多種故障檢測器,包含[15]與[5]中所描述的故障檢測器.我們得到的經驗是,隨著叢集規模的增長,檢測到故障的時間也會出現增長,超出了我們的接受限度.在一個特定的包含100個節點的實驗中,檢測一個故障節點竟然耗費大約2分鐘的時間.在我們的環境中,這實際上是不可接受的.利用accrual故障檢測器並設定一個稍顯保守的PHI(Φ)值(設定為5),在上面的實驗中檢測到故障的平均時間大約為15秒.
  • 不要對監控想當然.Cassandra系統與Ganglia[12]做了很好的整合,Ganglia是一個分散式的效能監控工具.我們向Ganglia開放了各種系統級別的指標,在Cassandra部署到我們的生產環境時,這一點幫助我們更深的理解了這個系統的行為.磁碟會無緣無故地出現故障.當磁碟出現故障時,引導演算法中有多個異常分支(hook)來修復這個節點.但是,這實際上是一個管理操作.
  • 雖然Cassandra是一個完全分散地系統,我們瞭解到,為了使一些分散式特性的實現更加可控,支援一定數量的協調操作還是非常必要的.我們打算對部分關鍵特性使用Zookeeper抽象,這些特性實際上與使用Cassandra作為儲存引擎的應用關係不大.

6.1 Facebook的收件箱搜尋

對於收件箱搜尋,我們為每個使用者維護了一份所有訊息的索引,這些訊息包含使用者作為傳送者的訊息也包含其作為接收者的訊息.目前啟用了兩種型別的索引(a)術語搜尋(b)互動搜尋,根據與此使用者給定互動的人的名稱返回使用者傳送給此人以及從此人處接收的所有訊息.這個概要(schema)包含兩個column family,對於查詢(a),用user id作為鍵(key),以構成訊息的單詞作為超級列(super column).對於查詢(b),user id仍然是鍵(key),接收者的id都是super column.對於這些super column中的每一個,單個訊息的識別符都是列.為了實現快速檢索,Cassandra為資料的智慧快取提供了特定的鉤子(hook)程式碼.例如,當使用者點選到搜尋欄時,會有一條非同步訊息傳送給Cassandra叢集,再通過使用者索引在快取記憶體(buffer cache)中準備好該使用者的資料.這樣,當實際的搜尋查詢請求到達時,搜尋結果很可能已經在記憶體中了.目前,這個系統在150個節點的叢集上儲存了大約50多TB的資料,這些節點分佈在美國東西海岸的多個資料中心.下面展示了部分生長環境中測量出來的讀效能資料.

延時統計搜尋互動術語
最小 7.69ms 7.78ms
中數 15.69ms 18.27ms
最大 26.13ms 44.41ms

7. 結論

我們已經建立、實現並維護的儲存系統,可以提供可伸縮性、高效能與廣泛的適用性.我們的經驗表明,Cassandra可以在提供低延時(low latency)的同時提高非常高的更新吞吐量(thoughput).後期的工作涉及增加壓縮功能、跨越多個鍵的原子操作支援以及輔助索引支援.

8. 致謝

Cassandra極大地受益與Facebook公司內部許多同事的反饋.另外還要特別感謝Karthik Ranganathan,他對MySQL中的所有資料建立了索引並將這些資料遷移到Cassandra中作為我們第一份正式部署.另外還要感謝來自EPFL的Dan Dumitriu,感謝他對我們提出的寶貴建議(關於[19]與[8]).

9. 參考文獻

[1] MySQL AB. Mysql.
[2] Atul Adya, William J. Bolosky, Miguel Castro, Gerald Cermak, Ronnie Chaiken, John R. Douceur, Jon Howell, Jacob R. Lorch, Marvin Theimer, and Roger P. Wattenhofer. Farsite: Federated, available, and reliable storage for an incompletely trusted environment. In In Proceedings of the 5th Symposium on Operating Systems Design and Implementation (OSDI, pages 1-14, 2002.
[3] Mike Burrows. The chubby lock service for loosely-coupled distributed systems. In OSDI ’06: Proceedings of the 7th symposium on Operating systems design and implementation, pages 335-350, Berkeley, CA, USA, 2006. USENIX Association.
[4] Fay Chang, Jeffrey Dean, Sanjay Ghemawat, Wilson C. Hsieh, Deborah A. Wallach, Mike Burrows, Tushar Chandra, Andrew Fikes, and Robert E. Gruber. Bigtable: A distributed storage system for structured data. In In Proceedings of the 7th Conference on USENIX Symposium on Operating Systems Design and Implementation – Volume 7, pages 205-218, 2006.
[5] Abhinandan Das, Indranil Gupta, and Ashish Motivala. Swim: Scalable weakly-consistent infection-style process group membership protocol. In DSN ’02: Proceedings of the 2002 International Conference on Dependable Systems and Networks, pages 303-312, Washington, DC, USA, 2002. IEEE Computer Society.
[6] Giuseppe de Candia, Deniz Hastorun, Madan Jampani, Gunavardhan Kakulapati, Alex Pilchin, Swaminathan Sivasubramanian, Peter Vosshall, and Werner Vogels. Dynamo: amazonO? s highly available key-value store. In Proceedings of twenty-first ACM SIGOPS symposium on Operating systems principles, pages 205-220. ACM, 2007.
[7] Jeffrey Dean and Sanjay Ghemawat. Mapreduce: simplified data processing on large clusters. Commun. ACM, 51(1):107-113, 2008.
[8] Xavier D?efago, P?eter Urba?n, Naohiro Hayashibara, and Takuya Katayama. The φ accrual failure detector. In RR IS-RR-2004-010, Japan Advanced Institute of Science and Technology, pages 66-78, 2004.
[9] Sanjay Ghemawat, Howard Gobioff, and Shun-Tak Leung. The google file system. In SOSP ’03: Proceedings of the nineteenth ACM symposium on Operating systems principles, pages 29-43, New York, NY, USA, 2003. ACM.
[10] Jim Gray and Pat Helland. The dangers of replication and a solution. In In Proceedings of the 1996 ACM SIGMOD International Conference on Management of Data, pages 173-182, 1996.
[11] David Karger, Eric Lehman, Tom Leighton, Matthew Levine, Daniel Lewin, and Rina Panigrahy. Consistent hashing and random trees: Distributed caching protocols for relieving hot spots on the world wide web. In In ACM Symposium on Theory of Computing, pages 654-663, 1997.
[12] Matthew L. Massie, Brent N. Chun, and David E.Culler. The ganglia distributed monitoring system: Design, implementation, and experience. Parallel Computing, 30:2004, 2004.
[13] Benjamin Reed and Flavio Junquieira. Zookeeper.
[14] Peter Reiher, John Heidemann, David Ratner, Greg Skinner, and Gerald Popek. Resolving file conflicts in the ficus file system. In USTC’94: Proceedings of the USENIX Summer 1994 Technical Conference on USENIX Summer 1994 Technical Conference, pages 12-12, Berkeley, CA, USA, 1994. USENIX Association.
[15] Robbert Van Renesse, Yaron Minsky, and Mark Hayden. A gossip-style failure detection service. In Service,Tˇ Proc. Conf. Middleware, pages 55-70, 1996.
[16] Mahadev Satyanarayanan, James J. Kistler, Puneet Kumar, Maria E. Okasaki, Ellen H. Siegel, and David C. Steere. Coda: A highly available file system for a distributed workstation environment. IEEE Trans. Comput., 39(4):447-459, 1990.
[17] Ion Stoica, Robert Morris, David Liben-nowell, David R. Karger, M. Frans Kaashoek, Frank Dabek, and Hari Balakrishnan. Chord: a scalable peer-to-peer lookup protocol for internet applications. IEEE/ACM Transactions on Networking, 11:17-32, 2003.
[18] D. B. Terry, M. M. Theimer, Karin Petersen, A. J. Demers, M. J. Spreitzer, and C. H. Hauser. Managing update conflicts in bayou, a weakly connected replicated storage system. In SOSP ’95: Proceedings of the fifteenth ACM symposium on Operating systems principles, pages 172-182, New York, NY, USA, 1995. ACM.
[19] Robbert van Renesse, Dan Mihai Dumitriu, Valient Gough, and Chris Thomas. Efficient reconciliation and flow control for anti-entropy protocols. In Proceedings of the 2nd Large Scale Distributed Systems and Middleware Workshop (LADIS ’08), New York, NY, USA, 2008. ACM.
[20] Matt Welsh, David Culler, and Eric Brewer. Seda: an architecture for well-conditioned, scalable internet services. In SOSP ’01: Proceedings of the eighteenth ACM symposium on Operating systems principles, pages 230-243, New York, NY, USA, 2001. ACM.

相關文章