[翻譯] Cassandra 分佈式結構化存儲系統

Cassandra 分佈式結構化存儲系統

摘要

Cassandra 是一個分佈式存儲系統,用於管理分佈在許多商品服務器上的大量結構化數據,同時提供無單點故障(no single point of failure)的高可用服務。Cassandra 的目標是在數百個節點(可能分佈在不同的數據中心)的基礎設施上運行。在這種規模下,大大小小的組件都會連續出現故障。在面對這些故障時,Cassandra 管理持久狀態的方式推動了依賴於此服務的軟件系統的可靠性和可伸縮性。雖然在許多方面 Cassandra 很像一個數據庫,並在許多設計和實現策略上有很多共同之處,但 Cassandra 不支持一個完整的關係數據模型;相反,它為客戶提供了一個簡單的數據模型,支持對數據布局和格式的動態控制。Cassandra系 統的設計是為了在廉價的硬件上運行,在不犧牲讀效率的情況下有高的寫吞吐量。

1.概述

Facebook 運營着最大的社交網絡平台,在高峰時期,它通過位於世界各地許多數據中心的數萬台服務器為數億用戶提供服務。Facebook 平台在性能、可靠性和效率方面都有嚴格的運營要求,為了支持平台的持續增長,平台需要具有高度的可擴展性。處理由數千個組件組成的基礎設施中的故障是我們的標準操作模式;在任何給定的時間,總是有少量但數量可觀的服務器和網絡組件出現故障。因此,軟件系統需要以一種將失敗視為規範而不是異常的方式來構建。為了滿足上述可靠性和可擴展性的需求,Facebook 研發了Cassandra。

Cassandra 綜合使用了一些著名的技術來實現可伸縮性和可用性。Cassandra 旨在滿足收件箱搜索問題(InBox Search Problem)的存儲需求。收件箱搜索是一個功能,用戶可以搜索他們的 Facebook 收件箱。在 Facebook,這意味着系統需要處理非常高的寫吞吐量,每天數十億的寫操作,並隨着用戶數量的增加而擴展。由於用戶是由地理分佈的數據中心服務的,因此能夠跨數據中心複製數據是降低搜索延遲的關鍵。收件箱搜索在2008年6月推出,大約有1億用戶,今天我們有超過2.5億用戶,到目前為止 Cassandra 一直都能支撐。Cassandra 現在被部署為多個服務的後端存儲系統。

本論文的結構如下:第2節是相關的工作,其中一些工作對我們的設計有很大的影響。第3節更詳細地介紹了數據模型。第4節將介紹客戶端API的概述。第5節介紹了系統設計和使 Cassandra 工作的分佈式算法。第6節詳細介紹了使用 Cassandra 工作和改進性能的經驗。在第6.1節中,我們描述了 Facebook 平台中的一個應用程序是如何使用 Cassandra 的。最後第7節總結了關於 Cassandra 的未來工作。

2.相關工作

分佈式數據的性能、可用性和持久性已經在文件系統和數據庫領域得到了廣泛的研究。與P2P存儲系統相比,P2P存儲系統只支持平面命名空間(flat namespaces),而分佈式文件系統通常支持分層命名空間(hierarchical namespaces)。像 Ficus 和 Coda 這樣的系統會以犧牲一致性為代價來複制文件以實現高可用性。通常使用專門的衝突解決程序來管理更新衝突。Farsite 是一個不使用任何集中式服務器的分佈式文件系統。Farsite 使用複製實現了高可用性和可擴展性。Google 文件系統 (GFS) 是另一個分佈式文件系統,用於託管 Google 內部應用程序的狀態。 GFS 使用簡單的設計,使用單個主服務器來託管整個元數據,並將數據分成塊並存儲在塊服務器中。然而,GFS 主服務器現在使用 Chubby 抽象來實現容錯。Bayou 是一個分佈式的關係數據庫系統,允許斷開連接的操作,並提供最終的數據一致性。在這些系統中,Bayou、Coda 和 Ficus 允許斷開連接的操作,並對網絡分區和中斷等問題具有彈性。這些系統的衝突解決程序各不相同。例如,Coda 和 Ficus 執行系統級衝突解決,而 Bayou 允許應用程序級解決。然而,所有這些都保證了最終的一致性。與這些系統類似,Dynamo 允許在網絡分區期間繼續進行讀取和寫入操作,並使用不同的衝突解決機制解決更新衝突,如一些客戶端驅動。傳統的複製關係數據庫系統關注的是保證複製數據的強一致性問題。儘管強一致性為應用程序編寫者提供了一種方便的編程模型,但這些系統在可擴展性和可用性方面受到限制[10]。這些系統無法處理網絡分區,因為它們通常提供強大的一致性保證(CAP理論)。

Dynamo 是亞馬遜用來存儲和檢索用戶購物車的存儲系統。Dynamo 基於 Gossip 的成員資格算法(membership algorithm)可幫助每個節點維護有關每個其他節點的信息。 Dynamo 可以定義為一個結構化的覆蓋,最多具有一跳請求路由。Dynamo 使用矢量時鐘方案檢測更新的衝突,但更傾向於客戶端衝突解決機制。Dynamo 中的寫入操作還需要執行讀取以管理向量時間戳。在系統需要處理非常高的寫入吞吐量的環境中,這可能會受到很大限制。Bigtable 提供結構和數據分佈,但依賴於分佈式文件系統的持久性。

3.數據模型

Cassandra 中的表是由鍵索引的分佈式多維映射。值是高度結構化的對象。表中的行鍵(row key)是一個沒有大小限制的字符串,儘管通常有 16 到 36 個位元組長。無論讀取或寫入多少列,單個行鍵下的每個操作在每個副本上都是原子的。列被分組到一個集合中,這個集合被稱為列族(column families),這與 Bigtable 系統中發生的情況非常相似。 Cassandra 公開了兩種列族,簡單列族和超列族。可以將超列族視作是列族中的一個列族。

此外,應用程序可以指定超列族或簡單列族中列的排序順序。系統允許按時間或名稱對列進行排序。收件箱搜索等應用程序利用列的時間排序,其中結果始終按時間排序順序顯示。使用規約 column_family:column 訪問列族中的任何列,使用 column_family:super_column:column 訪問列族中屬於 super 類型的任何列。6.1 節給出了超列族抽象能力的一個很好的例子。通常應用程序使用一個專用的 Cassandra 集群並將它們作為其服務的一部分進行管理。儘管系統支持多個表的概念,但所有部署的架構中只有一個表。

4.API

Cassandra API 由以下三種簡單的方法組成:

  • insert(table, key, rowMutation)
  • get(table, key, columnName)
  • delete(table, key, columnName)

columnName 可以引用列族中的特定列、列族、超列族或超列族中的列族。

5.系統架構

需要在生產環境中運行的存儲系統的架構很複雜。系統除了實際的數據持久化組件外,還需要具備以下特點;用於負載平衡、成員資格和故障檢測、故障恢復、副本同步、過載處理、狀態轉移、並發和作業調度、請求編組(request marshalling)、請求路由、系統監控和警報以及配置管理的可擴展且強大的解決方案。描述每個解決方案的細節超出了本文的範圍,因此我們將重點介紹 Cassandra 中使用的核心分佈式系統技術:分區、複製、成員資格、故障處理和擴展。所有這些模塊都是以同步工作的方式處理讀取/寫請求。通常,對鍵的讀/寫請求會被路由到 Cassandra 集群中的任何節點。然後該節點確定該特定鍵的副本。對於寫入,系統將請求路由到副本並等待一定數量的副本確認寫入完成(waits for a quorum of replicas to acknowledge the completion of the writes)。對於讀取,根據客戶端要求的一致性保證,系統要麼將請求路由到最近的副本,要麼將請求路由到所有副本並等待法定人數(a quorum of)的響應。

譯者註:關於 Quorum 相關知識點,可以詳見《分佈式系統模式-Quorum》

5.1 分區(Partitioning)

Cassandra 的關鍵設計特性之一是增量擴展的能力。這需要能夠在集群中的一組節點(即存儲主機)上動態劃分數據。Cassandra 使用一致性哈希在集群中對數據進行分區,但使用了一個保持順序的哈希函數。在一致性哈希中,哈希函數的輸出範圍被視為一個固定的圓形空間或「環」(即最大的哈希值環繞到最小的哈希值)。在這段空間中,系統中的每個節點都是一個帶符號的隨機值,表示它在環上的位置。通過對數據項的鍵進行哈希處理以產生其在環上的位置,然後將由鍵標識的每個數據項分配給一個節點,然後順時針遍歷環以找到位置大於該項位置的第一個節點。此節點被視為此鍵的協調器。應用程序指定此鍵,Cassandra 使用它來路由請求。因此,每個節點都負責環中它與其在環上的前任節點之間的區域。一致性哈希的主要優點是節點的斷開或連接僅影響其直接鄰居,而其他節點不受影響。一致性哈希算法提出了一些挑戰。首先,環上每個節點的隨機位置分配導致數據和負載分佈不均勻。其次,基本算法忽略了節點性能的異質性。通常有兩種方法來解決這個問題:一種是將節點分配到圓中的多個位置(如在 Dynamo 中),第二種是分析環上的負載信息,讓負載較輕的節點在環上移動,以減輕負載較重的節點。Cassandra 選擇後者,因為它使設計和實現非常容易處理,並有助於對負載平衡做出非常確定的選擇。

譯者註:關於一致性哈希算法的細節可以詳見://kb.cnblogs.com/page/42734/

5.2 複製(Replication)

Cassandra 使用複製來實現高可用性和持久性。每個數據項在N台主機上複製,其中N是「每個實例」配置的複製因子。每個鍵k都分配給一個協調節點(在上一節中描述)。協調器負責在其範圍內的數據項的複製。此外,除了本地存儲其範圍內的每個鍵,協調器還在環中的 N-1 個節點上複製這些鍵。Cassandra 為客戶提供了各種數據複製方式的選項。Cassandra 提供了各種複製策略,例如「機架非感知(Rack Unaware)」、「機架感知(Rack Aware)」(在數據中心內)和「數據中心感知(Datacenter Aware)」。副本是根據應用程序選擇的複製策略選擇的。如果某個應用程序選擇”Rack Unaware“複製策略,則通過選擇環上協調器的 N-1 個後繼節點來選擇非協調器副本。對於”Rack Aware“和”Datacenter Aware“策略,算法稍微複雜一些。Cassandra 系統使用一個叫做 Zookeeper 的系統在它的節點中選舉一個 leader。加入集群的所有節點都會與 leader 交互,leader 告訴他們是哪些範圍的副本,領導者儘力維護不變量,即沒有節點負責環中超過 N-1 個範圍。有關節點負責範圍的元數據在每個節點都會本地緩存,並在 Zookeeper 內部以容錯方式緩存;這樣,即使節點崩潰了,但是由於知道它負責的範圍可以迅速進行恢復。我們借用 Dynamo 的說法,並將負責給定範圍的節點視為該範圍的「偏好列表」。

如第 5.1 節所述,每個節點都知道系統中的每個其他節點,因此知道它們負責的範圍。Cassandra 通過放寬 5.2 節中描述的仲裁要求(quorum requirements),在存在節點故障和網絡分區的情況下提供持久性保證。數據中心會由於停電、冷卻故障、網絡故障和自然災害等發生故障。Cassandra 的配置使得每一行都可以跨多個數據中心進行複製。本質上,鍵的偏好列表是這樣構造的:即存儲節點分佈在多個數據中心。這些數據中心通過高速網絡鏈路連接(high speed network links)。這種跨多個數據中心進行複製的方案使我們能夠處理整個數據中心的故障而不會出現任何中斷。

譯者註:Leader 選舉是通過 Zookeeper 完成的,關於選舉相關知識點,可以詳見《分佈式系統模式-Leader-Followers》

5.3 成員資格(Membership)

Cassandra 中的集群成員資格基於 Scuttlebutt,這是一種非常有效的基於 Gossip 的反熵機制。 Scuttlebutt 的顯着特點是它具有非常高效的 CPU 利用率以及 gossip 通道的高利用率。在 Cassandra 系統內,Gossip 不僅用於成員資格,還用於傳播其他系統相關的控制狀態。

譯者註:關於 Gossip 協議可詳見《分佈式系統模式-Gossip 協議》

5.3.1 故障檢測(Failure Detection)

故障檢測是一種機制,通過這種機制,節點可以在本地確定系統中其他任何節點是否正常運行。在 Cassandra 中,故障檢測還用於避免在各種操作期間試圖與不可達節點通信。Cassandra 使用Phiφ積累故障檢測(Phi φ Accrual Failure Detection)的修改版本。 Accrual Failure Detection 的方法是,故障檢測模塊不會發出一個布爾值來說明節點是否啟動或關閉。相反,故障檢測模塊會發出一個表示每個受監控節點的猜想級別(suspicion level)的值。 該值定義為 φ。基本思想是在一個動態調整的尺度上表達 φ 的值,以反映受監控節點的網絡和負載狀況。φ 具有以下含義:給定某個閾值 φ,並假設我們決定在 φ = 1 時猜想是節點A,那麼我們將犯錯的可能性(即該決定在未來會因接收到心跳延遲)約為10%φ = 2 的可能性約為1%φ = 3 的可能性約為0.1%,以此類推。系統中的每個節點都維護着一個滑動窗口,該窗口是來自集群中其他節點的 gossip 消息的到達時間間隔。 確定這些到達間隔時間的分佈並計算 φ。 儘管原始論文表明該分佈近似於高斯分佈(Gaussian distribution),但由於 gossip 通道的性質及其對延遲的影響,我們發現指數分佈(Exponential distribution)是一個更好的近似值。據我們所知,我們在基於 Gossip 的環境中實施的 Accrual Failure Detection 是同類中的第一個。 Accrual Failure Detector 在準確性和速度方面都非常出色,並且它們還可以很好地適應網絡條件和服務器負載條件。

5.4 引導啟動(Bootstrapping)

當一個節點第一次啟動時,它會為其在環中的位置選擇一個隨機令牌。 為了容錯,映射被持久化到本地磁盤和 Zookeeper 中。然後令牌信息在集群中傳播。這就是我們知道所有節點及其在環中各自位置的方式。這使任何節點都可以將鍵請求路由到集群中的正確節點。在 bootstrap 案例中,當一個節點需要加入集群時,它會讀取其配置文件,該配置文件包含集群內一些聯繫點的列表(list of a few contact points)。我們稱這些初始接觸點為集群的種子(Seeds)。種子也可以來自像 Zookeeper 這樣的配置服務。在 Facebook 的環境中,節點中斷(由於故障和維護任務)通常是暫時的,但可能會持續較長時間。故障可能有多種形式,例如磁盤故障、CPU 故障等。節點中斷很少表示永久中斷,因此不應導致重新平衡分區分配或修復無法訪問的副本。同樣,手動錯誤可能會導致意外啟動新的 Cassandra 節點。為此,每條消息都包含每個 Cassandra 實例的集群名稱。如果配置中的手動錯誤導致節點嘗試加入錯誤的 Cassandra 實例,它可能會根據集群名稱進行阻止。由於這些原因,使用顯式機制來發起從一個 Cassandra 實例中添加和刪除節點的這種方法是合適的。管理員使用命令行工具或瀏覽器連接到 Cassandra 節點並發出成員資格更改以加入或離開集群。

5.5 集群擴容(Scaling the Cluster)

當一個新節點被添加到系統中時,它會被分配一個令牌,這樣它就可以減輕一個負載很重的節點。這導致新節點會承擔一個其他節點以前負責的範圍(分流)。操作員使用命令行實用程序或 Cassandra Web 儀錶板從系統中的任何其他節點啟動 Cassandra 引導算法。 放棄數據的節點使用內核-內核複製技術將數據流到新節點。 操作經驗表明,數據可以從單個節點以 40 MB/秒的速率傳輸。 我們正在努力通過讓多個副本參與引導傳輸來改進這一點,從而使工作並行化,類似於 Bittorrent。

5.6 本地持久化(Local Persistence)

Cassandra 系統依賴本地文件系統進行數據持久化。數據在磁盤上使用一種格式表示,該格式有助於高效數據檢索。典型的寫入操作包括實現持久性和可恢復性的寫入提交日誌以及更新內存中的數據結構。只有在成功寫入提交日誌後才會寫入內存數據結構。我們在每台機器上都有一個專門用於提交日誌的磁盤,因為所有寫入到提交日誌的操作都是順序的,所以我們可以最大限度地提高磁盤吞吐量。當內存中的數據結構超過某個閾值(根據數據大小和對象數量計算得出)時,它會將自身轉儲到磁盤。這種寫入是在機器配備的許多普通磁盤中的一個磁盤上執行的。所有寫入都是按順序寫入磁盤的,並且還會根據行鍵生成索引以進行有效查找。這些索引也與數據文件一起保存。隨着時間的推移,磁盤上可能存在許多這樣的文件,並且合併過程在後台運行以將不同的文件整理到一個文件中。這個過程與 Bigtable 系統中發生的壓縮過程非常相似。

典型的讀取操作首先查詢內存中的數據結構,然後再查看磁盤上的文件。這些文件按時間最新到最舊的順序查看。當發生磁盤查找時,我們可能會在磁盤上的多個文件中查找一個鍵。為了防止找到不存在該鍵的文件,布隆過濾器,匯總文件中的鍵,也存儲在每個數據文件中,並保存在內存中。首先使用這個布隆過濾器(bloom filter)來檢查正在查找的鍵是否確實存在於給定的文件中。列族中的一個鍵可以有很多列。需要一些特殊的索引來檢索離鍵較遠的列。為了防止掃描磁盤上的每一列,我們維護列索引,這允許我們跳轉到磁盤上的正確塊以進行列檢索(譯者註:就類似於b+樹的索引映射磁盤過程)。當給定鍵的列被序列化並寫入磁盤時,我們在每 256K 的塊邊界處生成索引。這個邊界是可配置的,但我們發現 256K 在我們的生產工作負載中工作得很好。

5.7 實現細節

單機上的 Cassandra 進程主要由以下幾個抽象部分組成:分區模塊、集群成員和故障檢測模塊以及存儲引擎模塊。這些模塊都依賴於一個事件驅動基層(event driven substrate ),其中消息處理管道(message processing pipeline)和任務管道(task pipeline)沿着 SEDA(分階段的事件驅動架構,stage event driver architecture) 結構模型被分割為多個階段。這些模塊中的每一個都是使用 Java 從頭開始實現的。集群成員和故障檢測模塊,建立在使用非阻塞I/O的網絡層之上。所有系統控制消息依賴於基於 UDP 的消息,而應用程序相關的複製消息和請求路由依賴於 TCP。請求路由模塊是使用特定的狀態機來實現的。當讀/寫請求到達集群中的任何節點時,狀態機會通過以下狀態變換:(i)識別擁有密鑰數據的節點(ii)將請求路由到節點並等待響應到達(iii)如果回復沒有在配置的超時值內到達,則請求失敗並返回給客戶端(iv)根據時間戳計算出最近的響應(v)如果任何副本沒有最新的數據塊,則安排對該副本的數據進行修復。為了說明,這裡不談故障場景。系統可以配置是執行同步寫入還是異步寫入。對於某些需要高吞吐量的系統,我們依賴異步複製。這裡的寫操作遠遠超過系統的讀操作。在同步情況下,我們在將結果返回給客戶端之前等待一定數量(a quorum of)的響應。

在任何有日誌記錄的系統中,都需要存在一種清洗(purging)提交日誌條目的機制。在 Cassandra 中,我們使用滾動提交日誌,在舊的提交日誌超過特定的、可配置的閾值大小後,新的提交日誌被滾出。我們發現,在 128MB 大小之後滾動提交日誌在我們的生產工作負載中似乎工作得很好。(譯者註:這裡其實指的是日誌分段與壓縮。整個過程的寫入都是順序寫的)每個提交日誌都有一個 header 頭,它基本上是一個位向量,它的大小是固定的,通常超過特定系統將處理的列族的數量。在我們的實現中,我們有一個內存數據結構和一個每個列族生成的數據文件。每次將特定列族的內存數據結構轉儲到磁盤時,我們都會在提交日誌中設置它的位,說明這列族已成功保存到磁盤。這表明該信息已被提交。這些位向量是每個提交日誌的,並且也在內存中維護。每次滾動提交日誌時,它的位向量和在滾動之前滾動的所有提交日誌的位向量都會被檢查。如果認為所有數據都已成功持久化到磁盤,那麼這些提交日誌將被刪除。對提交日誌的寫入操作可以是正常模式,也可以是快速同步模式。在快速同步模式下,對提交日誌的寫入被緩衝。這意味着機器崩潰時可能會丟失數據。在這種模式下,我們還以緩衝的方式將內存中的數據結構轉儲到磁盤。傳統數據庫並非旨在處理特別高的寫入吞吐量。Cassandra 將所有對磁盤的寫變為順序寫,從而最大限度地提高磁盤寫吞吐量。由於轉儲到磁盤的文件永遠不會發生變化,因此在讀取它們時不需要獲取鎖。對於讀/寫操作,Cassandra 的服務器實例實際上是無鎖的。因此,我們不需要處理或處理基於 B-Tree 的數據庫實現中存在的並發問題。

Cassandra 系統根據主鍵對所有數據進行索引。磁盤上的數據文件被分解成一系列塊。每個塊最多包含128個鍵,並由一個塊索引分隔。塊索引捕獲塊內鍵的相對偏移量及其數據的大小。當內存中的數據結構轉儲到磁盤時,會生成一個塊索引,並將它們的偏移量作為索引寫入磁盤。該索引也保存在內存中以便快速訪問。典型的讀操作總是首先在內存數據結構中查找數據。如果數據被找到,則將其返回給應用程序,因為內存中的數據結構包含任何鍵的最新數據。如果未找到,則我們以相反的時間順序對磁盤上的所有數據文件執行磁盤 I/O。因為我們總是在尋找最新的數據,所以我們首先查看最新的文件,如果找到數據就返回。隨着時間的推移,磁盤上的數據文件數量會增加。我們執行壓縮過程,非常類似於 Bigtable 系統,它將多個文件合併為一個;本質上是對一堆已排序的數據文件進行合併排序。系統將始終壓縮在大小方面彼此接近的文件,即永遠不會出現將 100GB 文件與小於 50GB 的文件壓縮的情況。定期運行一個主要的壓縮過程,將所有相關的數據文件壓縮成一個大文件。此壓縮過程是磁盤 I/O 密集型操作。可以進行許多優化以不影響即將到來的讀取請求。

關於日誌分段相關只是可以詳見《分佈式系統模式-日誌分段》

關於日誌壓縮的主要過程可以閱讀《設計數據密集型應用》,這裡給出譯者相關的了解內容,傳送門:日誌結構的合併樹

6.實踐經驗

在設計、實施和維護 Cassandra 的過程中,我們獲得了很多有用的經驗並吸取了很多教訓。一個非常基本的教訓是,在不了解應用程序使用的影響的情況下,不要添加任何新功能。 大多數有問題的場景不僅僅源於節點崩潰和網絡分區。我們在這裡只分享一些有趣的場景。

  • 在啟動收件箱搜索應用程序之前,我們必須為超過1億用戶索引 7TB 的收件箱數據,然後存儲在我們的 MySQL 基礎設施中,並將其加載到 Cassandra 系統中。整個過程涉及到對 MySQL 數據文件運行 Map/Reduce 作業,對它們進行索引,然後將反向索引存儲在 Cassandra 中。M/R 過程實際上表現為 Cassandra 的客戶端。我們為 M/R 進程公開了一些後台通道,以聚合每個用戶的反向索引並將序列化數據發送到 Cassandra 實例,以避免序列化/反序列化開銷。這樣,Cassandra 實例只會受到網絡帶寬的限制。
  • 多數應用程序只需要對每個副本的每個鍵進行原子操作。然而,也有一些應用程序要求進行事務處理,主要是為了維護二級索引。大多數具有多年使用 RDBMS 開發經驗的開發人員發現這是一個非常有用的特性。我們正在研究一種機制來公開這種原子操作。
  • 我們嘗試了各種故障檢測器的實現,例如 [15] 和 [5] 中描述的那些。我們的經驗是,隨着集群大小的增加,檢測故障的時間會增加到超過可接受的限度。在一個包含 100 個節點的集群中的特定實驗中,檢測故障節點所需的時間大約為兩分鐘。這在我們的環境中實際上是行不通的。採用權責發生故障檢測器,PHI值略保守,設置為5,上述實驗中檢測故障的平均時間約為15秒。
  • 監測不應被視為理所當然。Cassandra 系統與分佈式性能監控工具 Ganglia 很好地集成在一起。我們向 Ganglia 公開了各種系統級指標,這有助於我們了解系統在生產工作負載下的行為。磁盤沒有明顯的原因出現故障。引導算法有一些鉤子可以在磁盤故障時修復節點。然而,這是一個管理操作。
  • 儘管 Cassandra 是一個完全去中心化的系統,但我們已經了解到,一定程度的協調對於使某些分佈式功能的實現易於處理至關重要。例如 Cassandra 與 Zookeeper 集成,可用於大規模分佈式系統中的各種協調任務。我們打算將 Zookeeper 抽象用於一些實際上不會妨礙使用 Cassandra 作為存儲引擎的應用程序的關鍵特性。

6.1 Facebook 收件箱搜索

對於收件箱搜索,我們為郵件的發件人和收件人之間交換的所有郵件維護每個用戶索引。現在啟用了兩種搜索功能:(a) 詞條搜索;(b)交互,給定一個人的名字,返回用戶可能從那個人那裡發送或接收過的所有消息。該模式由兩個列族組成。對於查詢(a),用戶id是鍵,組成消息的單詞成為超列族(super column)。包含該單詞的消息的各個消息標識符成為超列族中的列族。對於查詢(b),用戶id是鍵,收件人id是超級列。對於這些每個超列族,單獨的消息標識符是列。為了加快搜索速度,Cassandra 提供了一些用於智能緩存數據的鉤子。 例如,當用戶單擊搜索欄時,會向 Cassandra 集群發送一條異步消息,以使用該用戶的索引來填充緩衝區緩存。這樣,當執行實際搜索查詢時,搜索結果很可能已經在內存中(譯者註:這是利用緩存局部性原理優化)。該系統目前在一個 150 個節點的集群上存儲了大約 50+TB 的數據,該集群分佈在東海岸和西海岸的數據中心之間。我們展示了一些用於讀取性能的生產測量數據:

延遲狀態(Latency Stat) 交互搜索 詞條搜索
Min 7.69ms 7.78ms
Median 15.69ms 18.27ms
Max 26.13ms 44.41ms

7.總結

我們已經構建、實現和操作了一個存儲系統-提供可伸縮性、高性能和廣泛的應用。我們已經通過經驗證明,Cassandra 可以在提供低延遲的同時支持非常高的更新吞吐量。未來的工作包括增加壓縮、支持跨鍵原子性和二級索引支持。

原文連接

Cassandra – A Decentralized Structured Storage System