基於列儲存的開源分散式NoSQL資料庫Apache Cassandra入門分享

2023-03-30 06:00:25

@

概述

定義

Apache Cassandra 官網地址 https://cassandra.apache.org/ 最新版本4.1.1

Apache Cassandra 官網檔案地址 https://cassandra.apache.org/doc/latest/

Apache Cassandra 原始碼地址 https://github.com/apache/cassandra

Apache Cassandra 是一個開源的分散式、高可用、最終一致性的NoSQL資料庫,可以快速、可延伸可靠的管理海量資料,無單點故障。

NoSQL,泛指非關係型的資料庫,NoSQL去掉關聯式資料庫的關係型特性,資料之間無關係,非常容易擴充套件。

  • 易擴充套件:NoSQL資料庫種類繁多,但是一個共同的特點都是去掉關聯式資料庫的關係型特性。資料之間無關係,這樣就非常容易擴充套件,在架構的層面上帶來了可延伸的能力。
  • 巨量資料量,高效能:NoSQL資料庫都具有非常高的讀寫效能,尤其在巨量資料量下。一般MySQL使用Query Cache。NoSQL的Cache是記錄級的,是一種細粒度的Cache,所以NoSQL在這個層面上來說效能就要高很多。
  • 靈活的資料模型:NoSQL無須事先為要儲存的資料建立欄位,隨時可以儲存自定義的資料格式。而在關聯式資料庫裡,增刪欄位是一件非常麻煩的事情。
  • 高可用:NoSQL在不太影響效能的情況,就可以方便地實現高可用的架構。比如Cassandra、HBase模型,通過複製模型也能實現高可用。

特性

  • 彈性可延伸性:允許新增更多的硬體以適應更多的客戶和更多的資料根據要求。
  • 無中心化架構:沒有單點故障,它可以連續用於不能承擔故障的關鍵業務應用程式。
  • 快速線性效能:增加叢集中的節點數量增加你的吞吐量。因此,保持一個快速的響應時間。
  • 靈活的資料儲存:包括:結構化,半結構化和非結構化。它可以根據您的需要動態地適應變化的資料結構。
  • 便捷的資料分發:通過在多個資料中心之間複製資料,可以靈活地在需要時分發資料。
  • 事務支援:支援屬性,如原子性,一致性,隔離和永續性(ACID)。
  • 快速寫入

與Hbase對比

  • 架構:HBASE起源於Google BigTable,幾乎遵從了BigTable論文的大多數架構設計。Cassandra則是採納了BigTable的資料模型,同時吸收了Amazon Dynamo的分散式設計。
    • 從儲存結構模型的微觀上看,HBASE和Cassandra在單點儲存資料的機理是類似的,但是從分散式架構的宏觀上看,兩者則大相徑庭。、
    • 從單點儲存模型上看起來兩者較為相似,有紀錄檔追加(WAL VS CommitLog),有記憶體寫入緩衝區(MemStore VS MemTable),也都刷盤(flush)到LSM-Tree結構的持久化檔案(StoreFile VS SSTable File),都用Bloomfilter和Row Index的組合模式進行行鍵的索引,它們也都是利用BigTable的資料模型結構實現高速的寫入和熱點資料的查詢。
    • 從分散式架構上HBASE是中心化架構並滿足分散式CAP定理中的CP(分散式一致性),強調資料寫入的強一致性;Cassandra是去中心化架構並滿足分散式CAP定理中的AP(分散式高可用),適應資料在讀取過程中完成最終一致性。
  • 關鍵特性
    • 由內看結構: 在查詢方面Cassandra還支援二級索引,內建CQL(MySQL的SQL語法接近),SSTable分層結構也側重定位與查詢;但HBase沒有二級索引,只強調列簇的行鍵scan,Region中的Store與HDFS密切配合,StoreFile中KV以順序排列,儲存強調整體的時間寫入順序。因此Cassandra就非常適合通過列欄位為條件來查詢,而HBase更擅長通過行掃描做列集分析。
      • 本質原因在於Cassandra的資料是基於一致性雜湊演演算法,按照HASH範圍劃分,實現記錄根據雜湊值在整個叢集節點的隨機分佈以及複本冗餘,那麼查詢起來更適合在整個叢集中對任何記錄進行大範圍的定位和查詢,充分利用叢集的整體算力;
      • 但是HBase是順序的寫入同一個Region,在資料量足夠大後再分裂,那麼HBase就不適合頻繁大範圍的對資料定位與查詢,更適合按行鍵做順序掃描的集合分析。查詢主要體現在就近和熱點資料上的高效能。
    • 由外看分散式: Cassandra的叢集去中心化主要利用一致性雜湊環機制實現資料的分佈和擴容縮容的資料遷移,利用gossip協定在對等節點的網路傳播下儲存叢集狀態一致性,利用anti-entropy(反熵)機制實現資料讀取過程中節點之間的比對,保證資料一致性,這些都是叢集在對等條件下基於機制而達成狀態上的共識,那麼Cassandra的這些特性,就使得叢集不能太大,太大就不好管理,也容易導致網路通訊過於密集。Cassandra這種去中心化架構表現出來的優點就是叢集無單點故障隱患,叢集健壯性高,可用性極高,運維很省事。HBASE以及所依賴的Hadoop HDFS都是基於中心化集中式管理,存在HMaster的叢集單點故障風險,因此一般HBASE的HMaster可以有一個或多個HA熱備,引入HA後的HBASE叢集依然很健壯,只是必然引入更高的部署複雜度,底層依賴的HDFS NameNode HA在服務部署複雜性方面則更甚之。
  • 適用場景:HBASE更側重分析,Cassandra則勝於查詢
    • Cassandra更適合在資料大吞吐的情況下,藉助資料分佈優勢,高速寫入,並通過二級索引實現SQL語法豐富的欄位級查詢,以及支援線上應用實時產生的超大規模資料的儲存,可以在大規模資料寫入與查詢的都比較適合的場景下替代MySQL,在事務和一致性要求不嚴格的環境下,為每天並行與寫入量驚人的線上業務系統,提供資料庫支撐。因此其面向服務的領域偏重oltp。
    • HBASE更適合管理著大規模叢集,並在超大規模資料之上進行實時的,結構化的海量資料支撐,而且滿足強一致性要求,達到行級事務要求,可以使其對接一些關鍵性業務在可靠性要求高的環境下支撐線上實時分析,例如電子商務交易,金融交易等等。但並不適合隨機性很強的查詢,更適合大吞吐的資料寫入,熱點資料的行級查詢以及大規模的掃描分析。並且具有Hadoop生態的數倉工具支撐。因此HBASE更面向olap。

Cassandra使用場景

  • 特徵
    • 資料寫入操作密集
    • 資料修改操作很少
    • 通過主鍵查詢
    • 需要對資料進行分割區儲存
  • 場景舉例
    • 儲存紀錄檔型資料
    • 類似物聯網的海量資料
    • 對資料進行跟蹤

術語

  • cluster:使用gossip協定交換訊息的兩個或多個資料庫範例。
  • commitlog:資料庫將更改後的資料追加到檔案,以便在故障後恢復。
  • datacenter:在叢集中一起設定的一組相關節點,用於複製和工作負載隔離。不一定是單獨的位置或物理資料中心。資料中心名稱區分大小寫,不能修改。
  • gossip:用於在節點之間交換位置和狀態資訊的對等通訊協定。
  • hint:除了read-repair和full/incremental anti-entropy repair之外,Cassandra實現的三種方法之一,也是最終一致性保證,最終確認所有更新最終被所有副本接收。
  • listen address:要繫結到的地址或介面,並告訴要連線到的其他Cassandra節點。
  • seed node:種子節點用於引導加入叢集的新節點。
  • snitch:節點IP地址到物理位置和虛擬位置(如機架和資料中心)的對映。
  • SSTable:提供了從鍵到值的持久的、有序的不可變對映,其中鍵和值都是任意的位元組字串。

架構

概覽

Cassandra是具有最終一致語意的分割區寬列儲存模型,最初是由Facebook設計的,它使用了一種分階段事件驅動架構(SEDA)來實現Amazon的Dynamo分散式儲存和複製技術以及谷歌的Bigtable資料和儲存引擎模型的組合。

Cassandra提供了Cassandra查詢語言(CQL),這是一種類似sql的語言,用於建立和更新資料庫模式以及存取資料。

  • Keyspace:定義每個資料中心如何複製資料集。複製是指每個叢集儲存的副本數量。鍵空間包含表。
  • Table:定義分割區集合的型別化模式。表包含分割區,分割區包含行,行包含列。Cassandra表可以靈活地向表中新增新列,並且零停機時間。
  • Partition:定義主鍵的強制部分,Cassandra中的所有行都必須識別儲存該行的叢集中的節點。所有效能查詢都在查詢中提供分割區鍵。
  • Row:包含由唯一主鍵標識的列集合,該主鍵由分割區鍵和可選的其他叢集鍵組成。
  • Column:具有屬於行型別的單個資料。

CQL在分割區資料集上支援許多高階特性,例如:

  • 具有原子比較和設定語意的單分割區輕量級事務。
  • 使用者定義的型別、函數和聚合
  • 集合型別包括集合、對映和列表。
  • 本地二級索引
  • 物化檢視(實驗階段)

Dynamo

Apache Cassandra依賴於Amazon的Dynamo分散式儲存鍵值系統的許多技術。Dynamo系統中的每個節點都有三個主要元件

  • 請求分割區資料集上的協調
  • 環成員和故障檢測
  • 本地永續性(儲存)引擎

Cassandra主要利用前兩個叢集元件,同時使用基於紀錄檔結構化合並樹(Log Structured Merge Tree, LSM)的儲存引擎。特別是Cassandra依賴於Dynamo風格:

  • 使用一致雜湊進行資料集分割區
  • 使用版本化資料和可調一致性的多主複製
  • 通過gossip協定進行分散式叢整合員和故障檢測
  • 在商用硬體上的增量擴充套件

Cassandra滿足大規模(PiB+)業務關鍵型儲存需求。特別是由於應用程式要求對pb級資料集進行完整的全球複製,同時還需要始終可用的低延遲讀寫。

資料集分割區使用令牌環的一致性雜湊

使用令牌環的一致性雜湊:Cassandra使用一種稱為一致雜湊的特殊雜湊形式在儲存節點上劃分資料。在樸素資料雜湊中,通常通過對鍵對桶數取模的雜湊來將鍵分配給桶。例如,如果您希望使用樸素雜湊將資料分佈到100個節點,您可以將每個節點分配到0到100之間的儲存桶,對輸入鍵取模100進行雜湊,並將資料儲存在相關的儲存桶中。然而,在這個簡單的方案中,新增一個節點可能會使幾乎所有對映失效。

相反,Cassandra將每個節點對映到一個連續雜湊環上的一個或多個令牌,並通過將一個鍵雜湊到環上,然後沿一個方向「行走」環來定義所有權,類似於Chord演演算法。一致雜湊與普通資料雜湊的主要區別在於,當要雜湊的節點(桶)數量發生變化時,一致雜湊只需要移動一小部分鍵。

  • 令牌:發電機樣式雜湊環上的單個位置。
  • 端點:網路上的單個物理IP和埠。
  • 主機ID:單個「物理」節點的唯一識別符號,通常出現在一個gEndpoint上,幷包含一個或多個gtoken。
  • 虛擬節點(或vnode):由相同物理節點擁有的雜湊環上的gToken,具有相同的gHost ID。

儲存引擎

  • CommitLog:提交紀錄檔是Cassandra節點本地所有突變的附加紀錄檔。寫入Cassandra的任何資料都將首先寫入提交紀錄檔,然後再寫入記憶表。這在意外停機的情況下提供了永續性。在啟動時,提交紀錄檔中的任何變化都將應用於memtables。
  • Memtables:memtable是Cassandra緩衝寫入的記憶體結構;通常,每個表都有一個活動的memtable;最終memtable被重新整理到磁碟上,成為不可變的sstable。
  • SSTables :SSTables 是Cassandra用於在磁碟上持久化資料的不可變資料檔案。當SSTables 從memtable被重新整理到磁碟或從其他節點被流式傳輸時,Cassandra觸發壓縮,將多個SSTables 合併為一個。一旦編寫了新的SSTables ,就可以刪除舊的SSTables 。

部署

單範例部署

# 通過官網下載下載最新的版本
wget https://dlcdn.apache.org/cassandra/4.1.1/apache-cassandra-4.1.1-bin.tar.gz
# 解壓
tar -xvf apache-cassandra-4.1.1-bin.tar.gz
# 進入目錄
cd apache-cassandra-4.1.1
# 啟動,如果是root使用者啟動bin/cassandra -R
bin/cassandra
# 檢視紀錄檔
tail -f logs/system.log
# 檢查Cassandra的狀態
bin/nodetool status

叢集部署

準備三臺192.168.2.100、192.168.2.101、192.168.2.102,選擇兩臺作為種子節點,分別在每臺上修改組態檔vim conf/cassandra.yaml

# 同一個叢集名稱一樣
cluster_name: 'Test Cluster'
# 種子地址,設定多個範例,用逗號隔開
seed_provider:
  - class_name: org.apache.cassandra.locator.SimpleSeedProvider
    parameters:
      - seeds: "192.168.2.100,192.168.2.101"
listen_address: 192.168.2.100
rpc_address: 192.168.2.100
# 下面檔案路徑按需修改,建議多個盤分開提高讀寫效能
# 資料檔案(如sstable)所在的一個或多個目錄,預設$CASSANDRA_HOME/data/data
data_file_directories: /data1/cassandra/data
# commitlog檔案所在的目錄
commitlog_directory: /data2/cassandra/commitlog
# 儲存快取的目錄
saved_caches_directory: /data3/cassandra/saved_caches
# hints所在的目錄
hints_directory: /data4/cassandra/hints

每臺的listen_address和rpc_address修改為本機對應的,修改設定分別啟動cassandra

# 需要先殺死原來的cassandra程序,也可以自己準備指令碼
ps -ef | grep cassandra
# 檢查Cassandra的狀態
bin/nodetool status
# 查詢關於令牌環的資訊
bin/nodetool ring

CQL

概述

Cassandra Query Language(CQL),CQL提供了一個類似於SQL的模型;資料儲存在包含行和列的表中。因此在本檔案中使用時,這些術語(表、行和列)具有與SQL中相同的定義。

  • Data types
  • Data definition language
  • Data manipulation language
  • Operators
  • Secondary indexes
  • Materialized views
  • Functions
  • JSON
  • CQL security
  • Triggers
  • Appendices
  • Changes

資料模型

  • 列(Column):列是Cassandra的基本資料結構單元,具有三個值:名稱,值、時間戳。在Cassandra中不需要預先定義列(Column),只需要在KeySpace裡定義列族,然後就可以開始寫資料了。
  • 列族( Column Family):列族不嚴謹來說相當於關聯式資料庫的表(Table),是包含了多行(Row)的容器。
    • 型別
      • 靜態column family(static column family):欄位名是固定的,比較適合對於這些column都有預定義的後設資料。
      • 動態column family(dynamic column family):欄位名是應用程式計算出來並且提供的,所以column family只能定義這些欄位的型別,無法不可以指定這些欄位的名字和值,這些名字和值是由應用程式插入某欄位才得出的。
    • Row key:ColumnFamily 中的每一行都用Row Key(行鍵)來標識,這個相當於關聯式資料庫表中的主鍵,並且總是被索引的
    • 主鍵:Cassandra可以使用PRIMARY KEY 關鍵字建立主鍵,分為2種
      • Single column Primary Key:如果 Primary Key 由一列組成稱為 Single column Primary Key。
      • Composite Primary Key:如果 Primary Key 由多列組成,那麼這種情況稱為 Compound Primary Key 或 Composite Primary Key。
    • 列族具有的屬性
      • keys_cached - 它表示每個SSTable保持快取的位置數。
      • rows_cached - 它表示其整個內容將在記憶體中快取的行數。
      • preload_row_cache -它指定是否要預先填充行快取。
  • 鍵空間 (KeySpace)
    • Cassandra的鍵空間(KeySpace)不嚴謹相當於關係型資料庫的資料庫,建立一個鍵空間就是建立了一個資料庫。鍵空間包含一個或多個列族(Column Family)。一般將有關聯的資料放到同一個 KeySpace 下面,鍵空間 (KeySpace) 建立的時候可以指定一些屬性:副本因子,副本策略,Durable_writes(是否啟用 CommitLog 機制)
    • 所有的副本都同樣重要,沒有主從之分。可以為每個資料中心定義副本因子。副本策略設定應大於1,但是不能超過叢集中的節點數。
  • 副本 (Replication):副本就是把資料儲存到多個節點,來提高容錯性。
  • 節點(Node):儲存資料的機器。
  • 資料中心(DateCenter):資料中心指叢集中所有的機器,組成了一個資料中心。
  • 叢集(Cluster):Cassandra資料庫是為跨越多條主機共同工作,對使用者呈現為一個整體的分散式系統設計的。Cassandra最外層容器被稱為群集。Cassandra將叢集中的節點組織成一個環(ring),然後把資料分配到叢集中的節點(Node)上。
  • 超級列:超級列是一個特殊列,因此它也是一個鍵值對。但是超級列儲存了子列的地圖。

資料型別

CQL是一種型別化語言,支援豐富的資料型別集,包括Native型別、集合型別、使用者定義型別、元組型別和自定義型別

  • Native型別:ASCII | BIGINT | BLOB | BOOLEAN | COUNTER | DATE | DECIMAL | DOUBLE | DURATION | FLOAT | INET | INT | SMALLINT | TEXT | TIME | TIMESTAMP | TIMEUUID | TINYINT | UUID | VARCHAR | VARINT
  • 集合型別:maps(使用大括號+鍵值)、sets(使用大括號)、lists(使用中括號)
  • 使用者定義型別:CQL支援定義使用者定義型別(udt)。可以使用create_type_statement、alter_type_statement和drop_type_statement來建立、修改和刪除這樣的型別。
  • 元組型別:CQL還支援元組和元組型別(其中元素可以是不同的型別)。從功能上講,元組可以作為具有匿名欄位的匿名UDT。

# CQL Shell 簡稱cqlsh,是一個可以和Cassandra資料庫通訊的使用者端,使用這個cqlsh使用者端可以執行Cassandra查詢語言(CQL)。指定IP和埠連線cql
./bin/cqlsh 192.168.2.100 9042
describe cluster;
describe keyspaces;
describe tables;

基礎操作

鍵空間

# 將輸出內容捕獲到名為outputfile的檔案
capture 'outputfile';
# 建立鍵空間
CREATE KEYSPACE school WITH replication = {'class':'SimpleStrategy', 'replication_factor' : 3};
# 檢視捕獲內容
cat outputfile

# 檢視鍵空間
DESCRIBE school;
# 使用鍵空間
use school;
# 修改鍵空間
ALTER KEYSPACE school WITH replication = {'class':'SimpleStrategy', 'replication_factor' : 1};
DESCRIBE school;
# 刪除鍵空間
DROP KEYSPACE school;

CREATE TABLE student(
   id int PRIMARY KEY,  
   name text,  
   age int,  
   gender tinyint,  
   address text ,
   interest set<text>,
   phone list<text>,
   education map<text, text>
);
# 列出當前鍵空間下所有表
DESCRIBE Tables;
# 檢視表資訊
DESCRIBE TABLE student; 

# 新增欄位
ALTER TABLE student ADD email text;
select * from student;
# 刪除欄位
ALTER table student DROP email;
select * from student
# 刪除表
DROP TABLE student;
# 清空表
TRUNCATE student;

key索引

  • Primary Key 主鍵:是用來獲取某一行的資料, 可以是單一列(Single column Primary Key)或者多列(Composite Primary Key)。在 Single column Primary Key 決定這一條記錄放在哪個節點。
create table test1 (  id int PRIMARY KEY,  name text);
  • Partition Key 分割區Key:在組合主鍵的情況下(上面的例子),第一部分稱作Partition Key(key_one就是partition key),第二部分是CLUSTERING KEY(key_two)Cassandra會對Partition key 做一個hash計算,並自己決定將這一條記錄放在哪個節點。如果 Partition key 由多個欄位組成,稱之為 Composite Partition key
create table test2 (  key_part_one int,  key_part_two int,  key_clust_one int,  key_clust_two int,  key_clust_three uuid,  name text,  PRIMARY KEY((key_part_one,key_part_two), key_clust_one, key_clust_two, key_clust_three));
  • Composite Primary Key 複合Key:如果 Primary Key 由多列組成,那麼這種情況稱為 Compound Primary Key 或 Composite Primary Key。執行建立表後,查詢testTab,會發現key_one和key_two 的顏色與其他列不一樣
create table test3 (  key_one int,  key_two int,  name text,  PRIMARY KEY(key_one, key_two));
  • Clustering Key 叢集:決定同一個分割區內相同 Partition Key 資料的排序,預設為升序,可以在建表語句裡面手動設定排序的方式。

索引

  • 普通列建立索引
# 為student的 name 新增索引,索引的名字為:sname, 命令:CREATE INDEX sname ON student (name);# 為student 的age新增索引,不設定索引名字,命令:CREATE INDEX ON student (age);DESCRIBE student;

可以發現 對age建立索引,沒有指定索引名字,會提供一個預設的索引名:student_age_idx。

索引原理:Cassandra之中的索引的實現相對MySQL的索引來說就要簡單粗暴很多了。Cassandra自動新建立了一張表格,同時將原始表格之中的索引欄位作為新索引表的Primary Key!並且儲存的值為原始資料的Primary Key。

  • 集合列建立索引
#  set集合新增索引CREATE INDEX ON student(interest);    #  map對映新增索引CREATE INDEX mymap ON student(KEYS(education));   # 刪除索引drop index sname;

運算元據

# 插入資料INSERT INTO student (id,address,age,gender,name) VALUES (1011,'南京路',10,2,'mike') ;# 修改資料UPDATE student set age = 11 where id= 1011;# 批次操作BEGIN BATCH    INSERT INTO student (id,address,age,gender,name) VALUES (1012,'長沙路',12,1,'joo') ;    INSERT INTO student (id,address,age,gender,name) VALUES (1015,'上海路',20,1,'Jack') ;    UPDATE student set age = 15 where id= 1012;    DELETE FROM student WHERE id=1011;APPLY BATCH;# 刪除資料DELETE FROM student WHERE student_id=1011;

# 更新map型別資料UPDATE student SET education={'中學': '城市第五中學', '小學': '城市第五小學'} WHERE id = 1012;# 更新list型別資料UPDATE student SET phone = ['020-66666666', '13666666666'] WHERE id = 1012;# 更新set型別資料UPDATE student SET interest = interest + {'遊戲'} WHERE id = 1012;

# 查詢條件
select * from student where interest CONTAINS '電影';

# 設定資料的ttl
INSERT INTO student (id,address,age,gender,name,interest, phone,education) VALUES (1030,'朝陽路30號',20,1,'Cary',{'運動', '遊戲'},['020-7777888','139876667556'],{'小學' :'第30小學','中學':'第30中學'}) USING TTL 20;

  • 本人部落格網站IT小神 www.itxiaoshen.com