四、副本存儲
Cassandra不像HBase是基於HDFS的分布式存儲,它的數據是存在每個節點的本地文件系統中。
Cassandra有三種副本配置策略:
1) SimpleStrategy (RackUnawareStrategy):
副本不考慮機架的因素,按照Token放置在連續下幾個節點。如圖3所示,假如副本數為3,屬於A節點的數據在B.C兩個節點中也放置副本。
2) OldNetworkTopologyStrategy (RackAwareStrategy):
考慮機架的因素,除了基本的數據外,先找一個處於不同數據中心的點放置一個副本,其余N-2個副本放置在同一數據中心的不同機架中。
3) NetworkTopologyStrategy (DatacenterShardStrategy):
將M個副本放置到其他的數據中心,將N-M-1的副本放置在同一數據中心的不同機架中。
五、網絡嗅探
網絡嗅探主要用來計算不同host的相對距離,進而告訴Cassandra網絡拓撲結構,以便更高效地對用戶請求進行路由。主要有三種配置策略:
1) org.apache.cassandra.locator.SimpleSnitch:
將不同host邏輯上的距離(Cassandra Ring)作為他們之間的相對距離。
2) org.apache.cassandra.locator.RackInferringSnitch:
相對距離是由rack和data center決定的,分別對應ip的第3和第2個八位組。即,如果兩個節點的ip的前3個八位組相同,則認為它們在同一個rack(同一個rack中不同節點,距離相同);如果兩個節點的ip的前兩個八位組相同,則認為它們在同一個數據中心(同一個data center中不同節點,距離相同)。
3) org.apache.cassandra.locator.PropertyFileSnitch:
相對距離是由rack和data center決定的,且它們是在配置文件cassandra-topology.properties中設置的。
六、一致性
在一致性上,Cassandra采用了最終一致性,可以根據具體情況來選擇一個最佳的折衷,來滿足特定操作的需求。Cassandra可以讓用戶指定讀/插入/刪除操作的一致性級別,一致性級別有多種,如圖5所示。

圖5 Cassandra一致性級別
注:一致性級別是由副本數決定,而不是集群的節點數目決定。
Quorum NRW協議中,只需W + R > N,就可以保證強一致性。一般來說,Quorum中比較典型的NRW為(3,2,2)。
維護最終一致性
Cassandra 通過4個技術來維護數據的最終一致性,分別為逆熵(Anti-Entropy),讀修復(Read Repair),提示移交(Hinted Handoff)和分布式刪除。
1) 逆熵
這是一種備份之間的同步機制。節點之間定期互相檢查數據對象的一致性,這里采用的檢查不一致的方法是 Merkle Tree;
2) 讀修復
客戶端讀取某個對象的時候,觸發對該對象的一致性檢查:
讀取Key A的數據時,系統會讀取Key A的所有數據副本,如果發現有不一致,則進行一致性修復。
如果讀一致性要求為ONE,會立即返回離客戶端最近的一份數據副本。然后會在后台執行Read Repair。這意味着第一次讀取到的數據可能不是最新的數據;如果讀一致性要求為QUORUM,則會在讀取超過半數的一致性的副本后返回一份副本給客戶端,剩余節點的一致性檢查和修復則在后台執行;如果讀一致性要求高(ALL),則只有Read Repair完成后才能返回一致性的一份數據副本給客戶端。可見,該機制有利於減少最終一致的時間窗口。
3) 提示移交
對寫操作,如果其中一個目標節點不在線,先將該對象中繼到另一個節點上,中繼節點等目標節點上線再把對象給它:
Key A按照規則首要寫入節點為N1,然后復制到N2。假如N1宕機,如果寫入N2能滿足ConsistencyLevel要求,則Key A對應的RowMutation將封裝一個帶hint信息的頭部(包含了目標為N1的信息),然后隨機寫入一個節點N3,此副本不可讀。同時正常復制一份數據到N2,此副本可以提供讀。如果寫N2不滿足寫一致性要求,則寫會失敗。 等到N1恢復后,原本應該寫入N1的帶hint頭的信息將重新寫回N1。
4) 分布式刪除
單機刪除非常簡單,只需要把數據直接從磁盤上去掉即可,而對於分布式,則不同,分布式刪除的難點在於:如果某對象的一個備份節點 A 當前不在線,而其他備份節點刪除了該對象,那么等 A 再次上線時,它並不知道該數據已被刪除,所以會嘗試恢復其他備份節點上的這個對象,這使得刪除操作無效。Cassandra 的解決方案是:本地並不立即刪除一個數據對象,而是給該對象標記一個hint,定期對標記了hint的對象進行垃圾回收。在垃圾回收之前,hint一直存在,這使得其他節點可以有機會由其他幾個一致性保證機制得到這個hint。Cassandra 通過將刪除操作轉化為一個插入操作,巧妙地解決了這個問題。
七、存儲機制
Cassandra的存儲機制借鑒了Bigtable的設計,采用Memtable和SSTable的方式。
CommitLog
和HBase一樣,Cassandra在寫數據之前,也需要先記錄日志,稱之為Commit Log,然后數據才會寫入到Column Family對應的MemTable中,且MemTable中的數據是按照key排序好的。SSTable一旦完成寫入,就不可變更,只能讀取。下一次Memtable需要刷新到一個新的SSTable文件中。所以對於Cassandra來說,可以認為只有順序寫,沒有隨機寫操作。
MenTable
MemTable是一種內存結構,當數據量達到塊大小時,將批量flush到磁盤上,存儲為SSTable。這種機制,相當於緩存寫回機制(Write-back Cache),優勢在於將隨機IO寫變成順序IO寫,降低大量的寫操作對於存儲系統的壓力。所以我們可以認為Cassandra中只有順序寫操作,沒有隨機寫操作。
SSTable
SSTable是Read Only的,且一般情況下,一個CF會對應多個SSTable,當用戶檢索數據時,Cassandra使用了Bloom Filter,即通過多個hash函數將key映射到一個位圖中,來快速判斷這個key屬於哪個SSTable。
為了減少大量SSTable帶來的開銷,Cassandra會定期進行compaction,簡單的說,compaction就是將同一個CF的多個SSTable合並成一個SSTable。在Cassandra中,compaction主要完成的任務是:
1) 垃圾回收: cassandra並不直接刪除數據,因此磁盤空間會消耗得越來越多,compaction 會把標記為刪除的數據真正刪除;
2) 合並SSTable:compaction 將多個 SSTable 合並為一個(合並的文件包括索引文件,數據文件,bloom filter文件),以提高讀操作的效率;
3) 生成 MerkleTree:在合並的過程中會生成關於這個 CF 中數據的 MerkleTree,用於與其他存儲節點對比以及修復數據。
詳細存儲數據結構參考 http://www.ibm.com/developerworks/cn/opensource/os-cn-cassandraxu2
Cassandra和HBase的一個重要區別是, Cassandra在每個節點是是一個單 Java 進程,而完整的HBase 解決方案卻由不同部分組成:有數據庫進程本身,它可能會運行在多個模式;一個配置好的 hadoop HDFS 分布式文件系統,以及一個 Zookeeper 系統來協調不同的 HBase 進程。