Cassandra

**Apache Cassandra**（社群內一般簡稱為 C\*）是一套開源分散式 NoSQL 資料庫系統。它最初由 Facebook 開發，用於改善電子郵件系統的搜尋效能的簡單格式資料，集 Google BigTable 的資料模型與 Amazon Dynamo 的完全分散式架構於一身。Facebook 於 2008 將 Cassandra 開源，此後，由於 Cassandra 良好的可延伸性和效能，被 Apple, Comcast,Instagram, Spotify, eBay, Rackspace, Netflix 等知名網站所採用，成為了一種流行的分散式結構化資料儲存方案。

在資料庫排行榜「DB-Engines Ranking」中，Cassandra 排在第十位，是非關聯型資料庫中排名第四高。

## 歷史

Cassandra 的名稱來源於希臘神話，是特洛伊的一位悲劇性的女先知的名字，因此專案的 Logo 是一隻放光的眼睛。

這個專案由就職於 Facebook 的 Avinash Lakshman（也是 Amazon Dynamo 的作者之一）和 Prashant Malik 在為 Facebook 的 Inbox 編寫。2008 年，Facebook 將專案開源，Cassandra 在 2009 年成為了 Apache 軟體基金會的 Incubator 專案，並在 2010 年 2 月走出孵化器，成為正式的基金會專案。目前這個專案主要由專門進行 Cassandra 商業化運作的 DataStax（頁面存檔備份，存於網際網路檔案館）公司來開發，也有一些來自其他公司或獨立的開發者。

### 主要版本和主要改進

* 0.6，2010 年 4 月發布，支援內建的快取。
* 0.7，2011 年 1 月發布，支援按欄建二級索引 (secondary indexes) 及線上修改表的結構定義
* 0.8，2011 年 6 月發布，支援 CQL 語言和零停機的線上升級
* 1.0，2011 年 10 月發布，支援資料壓縮，level compaction 和提高讀取效能
* 1.1，2012 年 4 月發布，支援 ssd 和機械硬碟混合使用
* 1.2，2013 年 1 月發布，支援虛擬節點 (一個機器在一致性雜湊環中擁有多個節點)、原子性的批次處理
* 2.0，2013 年 9 月發布，支援輕量級事務、觸發器、改進 compaction 效能，強制使用 Java7
* 2.1，2014 年 9 月 10 日發布
* 2.2 , 2015 年 7 月 20 日發布
* 3.0 , 2015 年 11 月 11 日發布
* 3.1 , 同樣 3.10 版本，使用類 tick-tock 發布模式，每月發布一次，偶數編號版本提供新功能和錯誤修正，而奇數編號版本只包括錯誤修正。
* 3.11 ，2017 年 6 月 23 日發布，作為穩定的 3.11 版本系欄，修復了上一個 tick-tock 功能版本的錯誤。

## 資料模型

Cassandra 使用了 Google 設計的 BigTable 的資料模型，與面向列 (row) 的傳統的關聯型資料庫或鍵值儲存的 key-value 資料庫不同，Cassandra 使用的是寬欄儲存模型 (Wide Column Stores)，每列資料由 row key 唯一標識之後，可以有最多 20 億個欄，每個欄有一個 column key 標識，每個 column key 下對應若干 value。這種模型可以理解為是一個二維的 key-value 儲存，即整個資料模型被定義成一個類似 map<key1, map<key2,value>> 的類型。

舊版的 Cassandra 與客戶端互動的方法是通過 thrift，而目前新版本的 Cassandra 採用與 SQL 語言類似的 CQL 語言來實現資料模型的定義和資料的讀寫。其中 BigTable 中的欄族 (Column Family) 在 Cassandra 中被稱作類似關聯型資料庫中的稱呼 —— 表 (table)，而 Cassandra/BigTable 中的 row key 和 column key 並稱為主鍵 (primary key)。

Cassandra 的 row key 決定了該列資料儲存在哪些節點中，因此 row key 需要按雜湊來儲存，不能順序的掃描或讀取，而一個 row 內的 column key 是順序儲存的，可以進行有序的掃描或範圍尋找。

## 儲存模型

與 BigTable 和其模仿者 HBase 不同，Cassandra 的資料並不儲存在分散式檔案系統如 GFS 或 HDFS 中，而是直接存於本地。與 BigTable 一樣，Cassandra 也是紀錄檔型資料庫，即把新寫入的資料儲存在記憶體的 Memtable 中並通過磁碟中的 CommitLog 來做持久化，記憶體填滿後將資料按照 key 的順序寫進一個唯讀檔案 SSTable 中，每次讀取資料時將所有 SSTable 和記憶體中的資料進行尋找和合併。這種系統的特點是寫入比讀取更快，因為寫入一條資料是順序計入 commit log 中，不需要隨機讀取磁碟以及搜尋。

## 分散式架構

Cassandra 的系統架構與 Dynamo 類似，是基於一致性雜湊的完全 P2P 架構，每列資料通過雜湊來決定應該存在哪個或哪些節點中。叢集沒有 master 的概念，所有節點都是同樣的角色，徹底避免了整個系統的單點問題導致的不穩定性，叢集間的狀態同步通過 Gossip 協定來進行 P2P 的通信。每個節點都把資料儲存在本地，每個節點都接受來自客戶端的請求。每次客戶端隨機選擇叢集中的一個節點來請求資料，對應接受請求的節點將對應的 key 在一致性雜湊的環上定位是哪些節點應該儲存這個資料，將請求轉發到對應的節點上，並將對應若干節點的查詢回饋返回給客戶端。

在一致性、可用性和分割區耐受能力（CAP）的折衷問題上，Cassandra 和 Dynamo 一樣比較靈活。Cassandra 的每個 keyspace 可組態一列資料會寫入多少個節點 (設這個數為 N)，來保證資料不因為機器宕機或磁碟損壞而遺失資料，即保證了 CAP 中的 P。使用者在讀寫資料時可以指定要求成功寫到多少個節點才算寫入成功 (設為 W)，以及成功從多少個節點讀取到了資料才算成功 (設為 R)。可推理得出，當 W+R>N 時，讀到的資料一定是上一次寫入的，即維護了強一致性，確保了 CAP 中的 C。當 W+R<=N 時，資料是最終一致性因為存在一段時間可能讀到的並不是最新版的資料。當 W=N 或 R=N 時，意味著系統只要有一個節點無回應或宕機，就有一部分資料無法成功寫或者讀，即失去了 CAP 中的可用性 A。因此，大多數系統中，都將 N 設為 3，W 和 R 設為 QUORUM，即「過半數」—— 在 N 為 3 時 QUORUM 是 2。

## 支援的操作

Cassandra 支援對一欄資料進行 insert、update、或 delete 操作。其中 insert 和 update 雖然語法略有區別，但語意上等價，即可以針對已經存在的列進行 update 或 insert 一個不存在的列。

### 輕量級事務

從 2.0 版開始，Cassandra 支援輕量級事務。這種事務被稱為「compare-and-set」，簡稱 CAS。通過 paxos 演算法實現在滿足某條件後才修改資料否則不修改。目前支援 "insert if not exist"、"update if col=value"、"delete if exist" 等幾種操作。

## 資料類型

Cassandra 在 CQL 語言層面支援多種資料類型。

## 與類似開源系統的比較

### Apache HBase

HBase 是 Apache Hadoop 專案的一個子專案，是 Google BigTable 的一個克隆，與 Cassandra 一樣，它們都使用了 BigTable 的欄族式的資料模型，但是：

* Cassandra 只有一種節點，而 HBase 有多種不同角色，除了處理讀寫請求的 region server 之外，其架構在一套完整的 HDFS 分散式檔案系統之上，並需要 ZooKeeper 來同步叢集狀態，部署上 Cassandra 更簡單。
* Cassandra 的資料一致性策略是可組態的，可選擇是強一致性還是效能更高的最終一致性；而 HBase 總是強一致性的。
* Cassandra 通過一致性雜湊來決定一列資料儲存在哪些節點，靠概率上的平均來實現負載均衡；而 HBase 每段資料 (region) 只有一個節點負責處理，由 master 來動態分配一個 region 是否大到需要拆分成兩個，同時會將過熱的節點上的一些 region 動態的分配給負載較低的節點，因此實現動態的負載均衡。
* 因為每個 region 同時只能有一個節點處理，一旦這個節點無回應，在系統將這個節點的所有 region 轉移到其他節點之前這些資料便無法讀寫，加上 master 也只有一個節點，備用 master 的恢復也需要時間，因此 HBase 在一定程度上有單點問題；而 Cassandra 無單點問題。
* Cassandra 的讀寫效能優於 HBase。

## 參考文獻

## 相關閱讀