Apache Cassandra 是一個開源的、分布式、去中心化、彈性可擴展、高可用性、容錯、一致性可調、面向行的數據庫,它基于 Amazon Dynamo 的分布式設計和 Google Bigtable 的數據模型。它最初由 Facebook 創建,用于儲存收件箱等簡單格式數據,于2008年開源。此后,由于 Cassandra 良好的可擴展性,被 Digg、Twitter 等知名 Web 2.0 網站所采納,成為了一種流行的分布式結構化數據存儲方案。
截止目前,Apache Cassandra 最新版本為 3.7。
Apache Cassandra 官方網站為 http://cassandra.apache.org/。
簡介
Cassandra 是 Facebook 于2008年7月在 Google Code 上開源的項目,最早是由 Amazon 前雇員和一位 Microsoft 的工程師寫成的。這個系統受到 Amazon Dynamo 的巨大影響(有關 Amazon Dynamo 的介紹,可以查閱論文《Dynamo: Amazon’s Highly Available Key-value Store》,網址為http://www.allthingsdistributed.com/files/amazon-dynamo-sosp2007.pdf)。Cassandra 實現了 Dynamo 風格的副本復制模型和沒有單點失效的架構,增加了更加強大的 column family 數據模型。
之后,在2009年1月,Cassandra 被接納為 Apache 基金會的孵化器項目,并于2010年3月畢業后成為了頂級項目。此時,很多知名公司包括 Facebook、Rackspace、Digg、Twitter 等都成為了 Cassandra 的用戶。
有關 Cassandra 論文,最早可見由 Facebook 的 Lakshman 和 Malik 發表的《A Decentralized Structured Storage System》(在線閱讀地址為 http://www.cs.cornell.edu/projects/ladis2009/papers/lakshman-ladis2009.pdf)。在 Cassandra 2.0 發布以后,Jonathan Ellis 對該論文相應的做了修改,發表于 http://docs.datastax.com/en/articles/cassandra/cassandrathenandnow.html。
伴隨著業界對于 Cassandra 商業化、產品化的需求,在2010年4月 Apache Cassandra 項目主席 Jonathan Ellis 以及其同事 Matt Pfeil 成立了一家服務公司,稱為 DataStax(原先的名字為 Riptano)。DataStax 雇傭了多名 Cassandra 貢獻者,成為了領導和支持 Cassandra 項目的主力。
2015年11月,Cassandra 發布了 3.0 版本,其底層的存儲引擎已被重寫,支持全局索引,支持 Java 8,并將基于 Thrift 命令行界面給移除了。
Apache Cassandra 具有如下特性:
1. 分布式與去中心化
Cassandra 是分布式的,這意味著它可以運行在多臺機器上,并呈現給用戶一個一致的整體。
對于很多存儲系統(如 MySQL、Bigtable、HBase 等),一旦你開始擴展它,就需要把某些節點設為主節點,其他則作為從節點。但 Cassandra 是去中心的,也就是說每個節點都是一樣的,沒有節點會承擔特殊的管理任務。與主從模式(master-slave)相反,Cassandra 的協議是 P2P 的,并使用 gossip 來維護存活或死亡節點的列表。
去中心化這一事實意味著 Cassandra 不會存在單點失效。Cassandra 集群中的所有節點的功能都完全一樣, 所以不存在一個特殊的主機作為主節點來承擔協調任務。有時這被叫做“server symmetry(服務器對稱)”。
綜上所述,因為 Cassandra 是分布式、去中心化的,它不會有單點失效的問題,所以支持高可用性。
2. 彈性可擴展
可擴展性是指系統架構可以讓系統提供更多的服務而不降低使用性能的特性。最簡單的達到可擴展性的手段,就是給現有的機器增加硬件的容量、內存進行垂直擴展。而水平擴展則需要增加更多機器,每臺機器提供全部或部分數據,這樣所有主機都不必負擔全部業務請求。但軟件自己需要有內部機制來保證集群中節點間的數據同步。
彈性可擴展是指水平擴展的特性,意即你的集群可以不間斷的情況下,方便擴展或縮減服務的規模。這樣,你就不需要重新啟動進程,不必修改應用的查詢,也無需自己手工重新均衡數據分布。在 Cassandra 里,你只要加入新的計算機,Cassandra 就會自動地發現它并讓它開始工作。
3. 高可用與容錯
系統的可用性是由滿足請求的能力來量度的。但計算機可能會有各種各樣的故障,從硬件器件故障到網絡中斷都有可能。所以它們一般都有硬件冗余,并在發生故障事件的情況下會自動響應并進行熱切換。從軟件的層次來說,設置多個數據中心,就是“軟件冗余”,它能保障在災難發生時,故障中斷的功能在剩余系統上能夠進行恢復。
Cassandra 就是高可用的。你可以在不中斷系統的情況下替換故障節點,還可以把數據分布到多個數據中心里,從而提供更好的本地訪問性能,并且在某一數據中心發生火災、洪水等不可抗災難的時候防止系統徹底癱瘓。
4. Tuneable Consistency(可調一致性)
一致性的基本含義是讀操作一定會返回最新寫入的結果。擴展數據存儲系統就意味著我們不得不在數據一致性、節點可用性和分區容錯性之間做某些折衷(即 CAP 理論)。Cassandra 常被稱作是“最終一致性”的,簡單地說,Cassandra 犧牲了一點一致性來換取了完全的可用性。但是 Cassandra 實際更應該表述為“可調一致性”,它允許你來方便地選定需要的一致性水平與可用性水平,在二者間找到平衡點。
因為客戶端可以控制在更新到達多少個副本之前,必須阻塞系統。這是通過設置 replication factor(副本因子)來調節與之相對的一致性級別。
通過 replication factor,你可以決定準備犧牲多少性能來換取一致性。 replication factor 是你要求更新在集群中傳播到的節點數(注意,更新包括所有增加、刪除和更新操作)。
客戶端每次操作還必須設置一個 consistency level(一致性級別)參數,這個參數決定了多少個副本寫入成功才可以認定寫操作是成功的,或者讀取過程中讀到多少個副本正確就可以認定是讀成功的。這里,Cassandra 把決定一致性程度的權利留給了客戶自己。
所以,如果需要的話,你可以設定 consistency level 和 replication factor 相等,從而達到一個較高的一致性水平,不過這樣就必須付出同步阻塞操作的代價,只有所有節點都被更新完成才能成功返回一次更新。而實際上,Cassandra 一般都不會這么來用,原因顯而易見(這樣就喪失了可用性目標,影響性能,而且這不是你選擇 Cassandra 的初衷)。而如果一個客戶端設置 consistency level 低于 replication factor 的話,即使有節點宕機了,仍然可以寫成功。
5. Row-Oriented(面向行)
Cassandra 不是真正意義上的“Column-Oriented(面向列)”的數據庫而是“Row-Oriented(面向行)”, 它的數據結構不是關系型的,而是一個多維稀疏哈希表。“稀疏”意味著任何一行都可能會有一列或者幾列,但每行都不一定(像關系模型那樣)和其他行有一樣的列。每行都有一個唯一的鍵值,用于進行數據訪問。所以,更確切地說,應該把 Cassandra 看做是一個有索引的、Row-Oriented 的存儲系統。
Cassandra 的數據存儲結構基本可以看做是一個多維哈希表。這意味著你不必事先精確地決定你的具體數據結構或是你的記錄應該包含哪些具體字段。這特別適合處于草創階段,還在不斷增加或修改服務特性的應用。而且也特別適合應用在敏捷開發項目中,不必進行長達數月的預先分析。對于使用 Cassandra 的應用,如果業務發生變化了,只需要在運行中增加或刪除某些字段就行了,不會造成服務中斷。
當然, 這不是說你不需要考慮數據。相反,Cassandra 需要你換個角度看數據。在 RDBMS 里, 你得首先設計一個完整的數據模型, 然后考慮查詢方式, 而在 Cassandra 里,你可以首先思考如何查詢數據,然后提供這些數據就可以了。
6. Flexible Schema(靈活的模式)
早期版本的 Cassandra 是忠實于 Bigtable 的設計,而采用的是“schema-free(無模式)”的數據模型,新的 column 可以被動態定義。schema-free 模式的數據庫在處理大數據時有非常強的擴展和高性能的優勢。但這種模式的主要缺點是在確定數據的含義和數據的格式時存在難點,而這限制了執行復雜查詢的能力。
Cassandra Query Language(CQL)正是為了解決上面提到的問題。CQL 它提供了一種通過類似于 Structured Query Language(SQL)的語法來定義的模式。起初,CQL 是基于 Apache Thrift 項目的 schema-free 接口來提供額外的 Cassandra 接口的。在這個過渡階段,模式是可選的,可以通過 CQL 來定義,也可以通過 Thrift API 來實現在添加新的 column 時動態擴展。
自 Cassandra 3.0 以來,將不推薦采用通過基于 Thrift API 來實現動態創建 column 的方式。Cassandra 的底層存儲已重新實現,并與 CQL 更緊密地結合起來。Cassandra 并不限制動態擴展模式,但它的工作方式已經顯著的不同了。CQL 的集合,如 list、set,特別是 map 提供在無結構化的格式里面添加內容的能力,從而能擴展現有的模式。CQL 還提供了改變列的類型的能力,以支持 JSON 格式的文本的存儲。
因此, Cassandra 是支持“靈活的模式”。
7. 高性能
Cassandra 在設計之初就特別考慮了要充分利用多處理器和多核計算機的性能,并考慮在分布于多個數據中心的大量這類服務器上運行。它可以一致而且無縫地擴展到數百臺機器。Cassandra 已經顯示出了高負載下的良好表現,在一個非常普通的工作站上,Cassandra 也可以提供非常高的寫吞吐量。而如果你增加更多的服務器,你還可以繼續保持 Cassandra 所有的特性而無需犧牲性能。
Cassandra 應用場景
盡管 Cassandra 設計精巧、功能出色,但也并非能勝任所有工作。所以,這里我們來介紹一下 Cassandra 最擅長的領域。
1. 大規模部署
Cassandra 的很多精巧設計都專注于高可用、可調一致性、P2P 協議、無縫擴展等,這些都是 Cassandra 的賣點。這些特性在單節點工作時都是沒有意義的,更無法展現它的全部能力。所以,你需要做一些評估,考慮你期望的流量、吞吐需求以及 SLA 等。如果你認為有幾種關系型數據庫可以很好地應付你的流量,提供不錯的性能,那可能選關系型數據庫更好。簡單地說,這是因為 RDBMS 更易于在單機上運行,對你來說也更熟悉。
但是,如果你認為需要至少幾個節點才能支撐你的業務,那 Cassandra 就是個不錯的選擇。如果你的應用可能需要數十個節點,那 Cassandra 可能就是個很棒的選擇了。
2. 寫密集、統計和分析型工作
Cassandra 是為優異的寫吞吐量而特別優化的。許多早期使用 Cassandra 的產品都用于存儲用戶狀態更新、社交網絡、建議/評價以及應用統計等。這些應用大都是寫多于讀的,并且更新可能隨時發生并伴有突發的峰值。事實上,支撐應用負載需要很高的多客戶線程并發寫性能,這正是 Cassandra 的主要特性。
Cassandra 已經被用于開發了多種不同的應用,包括窗口化的時間序列數據庫,用于文檔搜索的反向索引,以及分布式任務優先級隊列。
3. 地區分布
Cassandra 直接支持多地分布,可以很容易配置成將數據分布到多個數據中心的存儲方式。如果你有一個全球部署的應用,那么讓數據貼近用戶會獲得不錯的性能收益,Cassandra 正適合這種應用場合。
4. 變化的應用
如果你正在“初創階段”,業務會不斷改進,Cassandra 這種靈活的模式的數據模型可能更適合你。這讓你的數據庫能更快地跟上業務改進的步伐。
Cassandra 架構、數據模型
Cassandra 是設計來處理跨多個節點的大數據工作負載,且不會產生單點故障問題。它的架構是基于對系統和硬件故障也時有發生的理解,即計算機的故障不可避免。Cassandra 通過在集群中的所有節點之間分布均勻的節點,采用 P2P 的方式來定位分布式系統涉及的故障問題。每個節點經常交流有關其自身的狀態信息,其他節點利用 P2 gossip 通信協議與集群進行交互。Commit 日志在每個節點上會依次寫入活動信息,以確保數據的持久性,然后數據被索引并寫入內存結構 memtable 中。memtable 類似于一個回寫高速緩存。每次這個內存結構滿時,數據就被寫入磁盤中的 SSTable 數據文件中。所有的寫操作都會自動分區,并在整個集群中進行復制。Cassandra 定期合并使用一種稱為 compaction 過程來合并 SSTable,合并過程中會丟棄標記為 tombstone 的數據。為了確保所有的數據在整個集群保持一致,不同的修復機制將被使用。
Cassandra 是一個分區 row 存儲數據庫,其中 row 被組織成一個必需有主鍵的 table。 Cassandra 的架構允許任何已授權的用戶可以使用 CQL 語言來連接到任何數據中心的任何節點。為了方便使用,CQL 使用了類似的 SQL 的語法來操作表數據。開發人員可以通過 cqlsh、DevCenter 或者應用語言的驅動程序來訪問 CQL。通常情況下,集群都每個應用程序都會有一個 keyspace (密鑰空間),由許多不同的 table 組成。
客戶端讀取或寫入請求可以被發送到集群中的任何節點。當客戶端通過一個請求連接到一個節點時,則該節點充當協調器用于該客戶端特定的操作。協調器充當客戶端應用程序和擁有被請求數據的節點之間的代理。協調器來決定在哪些節點能收到請求,這往往是基于集群的配置要求。
Cassandra 包含如下核心構件:
- Node(節點):存儲數據的地方。它是 Cassandra 的基礎設施組件。
- Data center(數據中心):相關節點的集合。數據中心可以是物理數據中心或虛擬數據中心。不同的工作負載應使用單獨的數據中心,無論是物理的還是虛擬。復制是由數據中心的設置。使用單獨的數據中心可以防止由其他工作負荷受到影響卡桑德拉交易,并保持彼此接近為較低的延遲請求。根據不同的復制因子,可將數據寫入到多個數據中心。數據中心必須永遠跨越物理位置。
- Cluster(集群):一個集群包含一個或多個數據中心。它可以跨越物理位置。
-
Commit log(Commit 日志):
所有數據首先被寫入 Commit 日志以確保數據的持久性。當其所有的數據已沖刷到 SSTable 時,它可以存檔、刪除或回收。 -
SSTable:
SSTable(sorted string table,經排序的字符串表)是 Cassandra 定期寫 memtable 的不變的數據文件。SSTable 僅追加并在磁盤上依次存儲并保持 Cassandra table。 -
CQL Table:
通過 table row 獲取到的有序的 column 集合。table 由 column 和一個主鍵組成。
用于配置 Apache Cassandra 的核心組件
1. Gossip
P2P 通信協議用于發現和分享在 Cassandra 集群中的其他節點的位置和狀態信息。Gossip 信息也保存在每個節點本地,當一個節點重新啟動時可以被立即使用。
2. Partitioner(分區工具)
partitioner 用于確定哪些節點先接收第一個數據片段的副本,以及如何分配其他副本到集群的其他節點上。數據的每一 row 由唯一的主鍵來識別,該主鍵可以與 partition key(分區鍵)相同,但也可能包括了其他 clustering column。一個 partitioner 是一個是哈希函數,用于從 row 的主鍵中派生一個 token。partitioner 使用 token 值,以確定集群中哪些節點來接收該 row 的副本。Murmur3Partitioner 是新的 Cassandra 集群默認分區策略,在大部分情況下,也是在新的集群的正確選擇。
必須設置 partitioner,并為每個節點分配 num_tokens 值。token 的分配數量取決于系統的硬件功能。如果不能使用 virtual nodes(vnodes,虛擬節點),請使用 initial_token 設置來代替。
3. Replication factor(副本因子)
replication factor 是指集群副本的總數。replication factor 為 1 意味著一個節點上每個 row 僅有一個副本;為 2 意味著 每個 row 有2個副本,且每個副本位于不同節點上。所有副本都同樣重要,不區分是否是主副本。您需要為每個數據中心定義 replication factor。通常應設置策略大于1,但不超過集群中節點總數。
4. Replica placement strategy(副本放置策略)
Cassandra 存儲數據的副本到多個節點,以確??煽啃院腿蒎e性。復制策略決定哪些節點需要放置到副本上。第一個數據的副本是簡單的第一拷貝,它并不是唯一的。強烈建議大多數部署情況下使用 NetworkTopologyStrategy ,因為它在需要時更容易擴展到多個數據中心。
當創建一個 keyspace(密鑰空間),你必須定義副本放置策略和副本數。
5. Snitch
snitch 定義了數據中心的計算機組以及復制策略用于放置副本的機架(拓撲)。
當你創建一個集群時,必須配置一個 snitch。所有 snitch 使用動態 snitch 層,來監控性能,并選擇最佳副本來用于讀取。它是默認是啟用的,并推薦在大多數部署情況下使用。在 cassandra.yaml 配置文件里面來配置每個節點的動態 snitch 閾值。
默認 SimpleSnitch 不能識別的數據中心或機架的信息,可以在公共云的單數據中心部署或單區中使用它。建議在生產環境中使用 GossipingPropertyFileSnitch ,它定義了一個節點的數據中心和機架,并且使用 gossip 來傳播該信息到其他節點。
6. cassandra.yaml 配置文件
主配置文件用于設置集群的初始化屬性,比如 table 參數的緩存、調節屬性和資源利用率、超時設置、客戶端連接、備份、安全等。
默認情況下,節點被配置用于存儲受其管理的設置在 cassandra.yaml 文件的目錄下的數據。
在集群的生產部署環境,可以修改 commitlog-directory 目錄到與 data_file_directories 不同的磁盤驅動下。
7. 系統 keyspace table 屬性
你可以通過基本的編程方式來設置每個 keyspace 或 table 的存儲配置屬性,或者使用客戶端應用,比如 CQL。
Cassandra 安裝、配置、使用
本節將演示 Apache Cassandra 安裝、配置,以及通過命令行來使用 Cassandra。
1. 前置條件
- 最新版的 Java 8。Oracle Java Standard Edition 8(下載地址 http://www.oracle.com/technetwork/java/javase/downloads/index.html) 或 OpenJDK 8(下載地址為http://openjdk.java.net/)都行。安裝后,通過
java -version
來查看當前安裝的版本。 - 若使用 cqlsh,需要安裝最新版本的 Python 2.7。安裝后,通過
python --version
來查看當前安裝的版本。
2. 從編譯包來安裝
- 從 http://cassandra.apache.org/download/ 獲取安裝包。并解壓到任意目錄,例如:
tar -xvf apache-cassandra-3.6-bin.tar.gz cassandra
解壓后的目錄名為 apache-cassandra-3.6
。
- 可以選擇添加
apache-cassandra-3.6\bin
到您的路徑。 - 通過執行命令行
bin/cassandra -f
來在前臺啟動 Cassandra 按“Ctrl-C”來停止 Cassandra。通過執行命令行bin/cassandra
來在后臺啟動 Cassandra。調用kill pid
或pkill -f CassandraDaemon
來停止 Cassandra,其中 pid 是 Cassandra 的進程 ID,您可以通過pgrep -f CassandraDaemon
來查詢。 - 調用
bin/nodetool status
來驗證 Cassandra 是否在運行。 - 配置文件位于在
conf
子目錄。 - 自 Cassandra 2.1 以來,日志和數據目錄分別位于
logs
和data
子目錄下。舊版本默認在/var/log/cassandra
和/var/lib/cassandra
。由于這一點,就必須要么使用 root 權限或改變conf/ cassandra.yaml
中當前用戶所使用的用戶目錄。
3. 從 Debian 包來安裝
- 添加 Cassandra 的 repository(倉庫)到 /etc/apt/sources.list.d/cassandra.sources.list,例如 3.6 版本的配置如下:
echo "deb http://www.apache.org/dist/cassandra/debian 36x main" | sudo tee -a /etc/apt/sources.list.d/cassandra.sources.list
- 更新 repository
sudo apt-get update
- 如果遇到如下錯誤:
GPG error: http://www.apache.org 36x InRelease: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 749D6EEC0353B12C
就按如下方式來添加公鑰749D6EEC0353B12C
(該密鑰要根據你實際的出錯信息來獲?。?
gpg --keyserver pgp.mit.edu --recv-keys 749D6EEC0353B12C
gpg --export --armor 749D6EEC0353B12C | sudo apt-key add -
并再次執行 sudo apt-get update
。
- 安裝 Cassandra:
sudo apt-get install cassandra
- 執行
sudo service cassandra start
來啟動 Cassandra,執行sudo service cassandra stop
來停止。 - 執行
nodetool status
來驗證 Cassandra 是否在運行。 - 默認配置文件路徑在
/etc/cassandra
。 - 默認的日志和數據目錄在
/var/log/cassandra/
和/var/lib/cassandra
。
4. 配置集群
上述運行一個單節點 Cassandra,但若要部署集群,還要進行一些列參數的配置。
Cassandra 的配置文件在安裝文件的conf
目錄下, 對于包,配置文件將位于/etc/cassandra
。
(1)主運行屬性
大多數配置都在 cassandra.yaml
文件中配置,你至少需要配置下面的屬性:
-
cluster_name
:集群的名稱; -
seeds
:用逗號分隔的集群種子的 IP 地址列表; -
storage_port
:這項不一定要改,但請確保沒有防火墻阻止此端口; -
listen_address
:您的節點的 IP 地址,通過它來讓其他節點與該節點進行通信?;蛘撸部梢栽O置listen_interface
告訴 Cassandra 哪些接口可以使用,使用哪個連續的地址。設置一個即可,不能同時使用。
native_transport_port:作為storage_port,確保此端口不會被阻止通過防火墻的客戶端將與卡桑德拉此端口上進行通訊。
(2)更改目錄位置
下面是屬性是控制目錄的位置。
-
data_file_directories
:一個或多個數據文件位置的目錄; -
commitlog_directory
:commit log 文件所在的目錄; -
saved_caches_directory
:其中保存的緩存的位置目錄; -
hints_directory
: hints 所在的目錄。
由于性能原因,如果你有多個磁盤,考慮將 commit log 和數據文件放在不同的磁盤。
(3)環境變量
可以在cassandra-env.sh
進行 JVM 參數的設置,如堆大小等。您可以添加任何額外的 JVM 命令行參數到 JVM_OPTS
環境變量,當 Cassandra 啟動時,這些參數將被傳遞給 JVM。
(4)日志
日志框架是使用的 logback??梢孕薷?code>logback.xml來修改日志屬性。默認日志 INFO 級別是記錄在 system.log
文件,而 debug 級別記錄在debug.log
。當 Cassandra 是在前臺運行時,INFO 級別的信息會打印到控制臺。
5. 插入和查詢
使用 CQL 來進行插入和查詢操作。為了使用 CQL,首先要連接到集群,可以使用 cqlsh 或者客戶端應用的驅動。
(1)使用 CQLSH
cqlsh 是通過 CQL 與 Cassandra 交互的命令行 shell。該可執行命令,可以在bin/
目錄找到。例如,使用它連接到指定的單個節點:
$ bin/cqlsh localhost
Connected to Test Cluster at localhost:9042.
[cqlsh 5.0.1 | Cassandra 3.8 | CQL spec 3.4.2 | Native protocol v4]
Use HELP for help.
cqlsh> SELECT cluster_name, listen_address FROM system.local;
cluster_name | listen_address
--------------+----------------
Test Cluster | 127.0.0.1
(1 rows)
cqlsh>
可以參見 http://cassandra.apache.org/doc/latest/tools/cqlsh.html 來了解更多 cqlsh 的用法。
(2)使用客戶端應用的驅動
很多語言都提供了客戶端的驅動。在選擇驅動時,需要驗證 Cassandra 版本是否支持該驅動。
完整的驅動列表,可以參見 http://cassandra.apache.org/doc/latest/getting_started/drivers.html。