Cassandra

Apache Cassandra（社區內一般簡稱為C*）是一套開源分布式NoSQL資料庫系統。它最初由Meta開發，用於改善電子郵件系統的搜尋效能的簡單格式數據，集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>的類型。

舊版的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語言層面支持多種數據類型。

CQL類型｜對應Java類型｜描述

ascii｜String｜ascii字串

bigint｜long｜64位整數

blob｜ByteBuffer/byte｜二進位數組

boolean｜boolean｜布林

counter｜long｜計數器，支持原子性的增減，不支持直接賦值

decimal｜BigDecimal｜高精度小數

double｜double｜64位浮點數

float｜float｜32位浮點數

inet｜InetAddress｜ipv4或ipv6協議的ip地址

int｜int｜32位整數

list｜List｜有序的列表

map｜Map｜鍵值對

set｜Set｜集合

text｜String｜utf-8編碼的字串

timestamp｜Date｜日期

uuid｜UUID｜UUID類型

timeuuid｜UUID｜時間相關的UUID

varchar｜string｜text的別名

varint｜BigInteger｜高精度整型

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

### 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。

## 基本資料

- 日語原文：Apache Cassandra
- 作者：Avinash Lakshman、Prashant Malik
- 開發者：Apache軟體基金會
- 發行日期：2008年
- 程式語言：Java
- 作業系統：跨平台
- 語言：英文
- 類型：NoSQL資料庫
- 許可協議：Apache許可證2.0