咱們在《Apache Cassandra 簡介》文章中介紹了 Cassandra 的數據模型相似於 Google 的 Bigtable,對應的開源實現爲 Apache HBase,並且咱們在 《HBase基本知識介紹及典型案例分析》 文章中簡單介紹了 Apache HBase 的數據模型。按照這個思路,Apache Cassandra 的數據模型應該和 Apache HBase 的數據模型很相似,那麼這二者的數據存儲模型是否是同樣的呢?本文將爲你們解答這些問題。咱們從 KeySpace -> Table -> Partition -> Row -> Cell 順序介紹。本文基於 Apache Cassandra 3.11.4 源碼進行介紹的,不一樣版本可能有些不同。服務器
Cassandra 中的 KeySpace 概念和 RDBMS 裏面的 DataBase 概念很相似,一個 KeySpace 包含多張表,通常將有關聯的數據表放到同一個 KeySpace 下面。KeySpace 建立的時候能夠指定副本策略,副本因子以及是否啓用 CommitLog 機制(相似 HBase 中的 WAL)。spa
Cassandra 中表的概念和 RDBMS 很相似。不一樣的是在 Cassandra 中屬於同一張表的數據在物理上是分佈在不一樣節點上存儲的,同一張表由多個 Partition 組成。code
Cassandra 通常是由多臺節點組成的,每臺節點負責必定範圍的,若是使用 Murmur3hash 的時候,每一個節點負責的 Token 相似於下面那樣:blog
因此 Token 範圍爲 -9223372036854775808 ~ -4611686018427387904 的數據存儲在 A 節點;同理,Token 範圍爲 -4611686018427387903 ~ -1 之間的數據存儲在 B節點,其餘相似;每一個 Token 範圍由多個 Partition 構成,每一個 Partition 由一行或多行數據組成,Partition 相似下面的:
其中,username 爲 Partition key;type 爲 Clustering key。那麼在這種狀況下,username = iteblog 的兩條數據構成一個 Partition;另外兩條構成分別構成兩個 Partitions。在底層存儲每一個 Partition 格式以下:
從上圖能夠看出,一個 Partition 是由 PartitionHeader、零個或多個 Row (格式在後面介紹)以及 EndPartition 三部分組成的。EndPartition 這個用於標記 Partition 結束,只佔用一個字節,並使用 0x00000001 標記。PartitionHeader 的格式以下:排序
在底層存儲中,多個 Partition 組成一個 SSTable(Sorted-String Table)文件。那麼同一個 SSTable 文件中的數據數據是如何組織的呢?答案是按照 Partition Key 計算獲得的 Token 升序排序的。索引
上面看出,Partition 裏面包含了零個或多個 Row,這些 Row 對應的 Partition Key 是同樣的。非 Static 的 Row 在磁盤存儲的格式以下:
上面除了 flags 、Row Body Size 、 Previous Row Body Size 以及 Primary Key Liveness Timestamp 這四個字段必定會存在,其餘字段須要知足條件纔會存儲。下面對上面字段進行介紹:get
若是存在的列沒有佔總列數的一半,則按照所有列的順序保存存在的列在排序後列的索引位置;
若是存在的列佔總列數超過一半,則按照所有列的順序保存不存在的列在排序後列的索引位置。
可見,Cassandra 經過將列的信息(包括列的名稱、類型、表名、keySpace等信息)保存到對應 SSTable 的 md-X-big-Statistics.db 文件中,相應的行只保存列是否存在的標記信息,這個能夠節省存儲空間的佔用。注意,HBase 存儲數據的時候每一個 Cell 都須要保存列名稱和列族名稱的。源碼
非 Static Row 的底層存儲格式已經在前面描述過,對於 Static Row 除了沒有上圖的 Clustering info 信息,其他都同樣,因此這裏就不介紹了。hash
上圖中最後有 N 個 Cell,那多個 Cell 之間的順序是如何保證的呢?答案是按照列的名稱字典順序升序排序的。好比咱們表的定義以下:it
CREATE TABLE iteblog ( user_id text, type text, action text, username text, age text, email text, PRIMARY KEY(user_id) );
那麼 Cell 的順序排列以下:
action -> age -> email -> type -> username
這個排序是經過 BTree 實現的,Row 的實現類爲 BTreeRow。
Cell 就是每列數據的底層實現,Cell 裏面包含了列的定義信息,好比是否被刪除、是否過時、是否設置了時間戳等。在 Cassandra 裏面,Column 有 Simple 和 Complex(CASSANDRA-8099引入的) 之分。non-frozen collection 或 UDT(用戶自定義類型)的列是 ComplexColumn(Complex Cell)。
咱們正常使用的列就是屬於這種類型的,它的底層存儲格式以下:
若是列屬於 non-frozen collection 或 UDT(用戶自定義類型),那麼這個屬於 Complex Cell,它的底層存儲格式以下:
能夠看出,Complex Cell 和 Simple Cell 大部分很相似,下面只介紹不同的地方:
在 Cassandra 中, Complex Cell 的實現類是 ComplexColumnData。
原文連接 本文爲雲棲社區原創內容,未經容許不得轉載。