Cassandra – 理解關鍵概念和數據模型

Cassandra的設計理論傾向於實現CAP原則中的AP(Availability and Partition Tolerance)——高可用性和分佈式,它的分佈式是基於一致性哈希環(Consistent Hash Ring)算法實現的。 算法

面向行(Row-Oriented) 數據庫

咱們經常說Cassandra是一個面向列(Column-Oriented)的數據庫,其實這不徹底對——數據是以鬆散結構的多維哈希表存儲在數據庫中;所謂鬆散結構,是指每行數據能夠有不一樣的列結構,而在關係型數據中,同一張表的全部行必須有相同的列。在Cassandra中可使用一個惟一識別號訪問行,因此咱們能夠更好理解爲,Cassandra是一個帶索引的,面向行的存儲。 數組

無結構(Schema Free) 服務器

Cassandra只須要你定義一個邏輯上的容器(Keyspaces)裝載列族(Column Families),以後,你能夠自由地向列族中添加數據。每個列族都被設計爲一組數據關聯或排列。這種結構意味着,根據你的需求場景,你能夠只保存你須要的數據,而沒必要拘泥於早前定義的表結構。 數據結構

適用場景(Use Cases for Cassandra) 併發

  • 快速開發應用程序:Schema Free的特色,讓Cassandra能夠快速適應你的初期變動;若是你使用關係型數據庫,那麼就不得不從數據表、DAO層、Logic/Service層到UI層進行層層變動,哪怕只是一個小小的列名或字段類型變化; 運維

  • 大量寫入、統計和分析:Cassandra的列族設計是囊括數據關聯和排序的,而且能夠不存儲不須要的數據,這極大減省了表聯接和冗餘字段帶來的性能開銷,後者偏偏是高併發寫入操做、統計分析時關係型數據庫的瓶頸; 分佈式

  • 須要擴展的部署結構:Cassandra是面向分佈式的設計,這讓它能夠靈活地水平擴展,以在運維階段知足你的需求,而沒必要考慮「將數據遷往更高性能的服務器」這樣的問題。 ide

數據模型(Data Model) 高併發

咱們從最基本的概念來理解Cassandra的數據模型,先假設使用一個最簡單的值結構來存放一堆數據(Values)。

Screen Shot 2013-11-30 at 6.50.59 PM

但問題是,除非咱們記錄了每一個值的存放地址,咱們將沒法訪問到這些數據,這看起來很像一個數組或集合,咱們必須記住某個值的索引號,而且還要預先定義好這個數組的寬度,不然它會沒法容納足夠多的數據。

解決辦法是爲每一個數據添加一個惟一名稱(Name),只要咱們記住了這個名稱,就能找到這個數據了,這樣,咱們就有了一堆名稱——值對(Name/Value Pair)。

Screen Shot 2013-11-30 at 6.58.27 PM

這個結構很像哈希表,能夠知足一些信息的存儲,例如用戶的基本信息,姓、名、電話、手機、公司、地址等,而且咱們能夠根據須要來決定存儲哪些名稱和值,如此,咱們就獲得了一個單獨的行(Single Row),並引出了Cassandra數據庫中重要的行列概念定義:

一組包含名稱值對的數據叫作行(Row),而每一組名稱值對(Name/Value Pair)被稱之爲列(Column)。

Screen Shot 2013-11-30 at 7.11.01 PM

在關係型數據庫中,列的名稱必須是字符串,但在Cassandra中列名稱能夠爲任意類型,這意味着,你能夠將列名稱也做爲一個數據來存儲。換一種說法,你沒必要被數據類型約束,往Cassandra中添加數據就夠了。

下面的示例可讓咱們更好地理解Cassandra的數據存儲:

Musician:                           ColumnFamily 1 
    bootsy:                         RowKey 
        email: bootsy@pfunk.com,    ColumnName:Value 
        instrument: bass            ColumnName:Value 
    george:                         RowKey 
        email: george@pfunk.com     ColumnName:Value
Band:                               ColumnFamily 2 
    george:                         RowKey 
        pfunk: 1968-2010            ColumnName:Value

另外,Cassandra還有一種可在列之間創建關聯的超級列(Super Column),你能夠往超級列中添加子列。

Screen Shot 2013-11-30 at 7.17.58 PM

鍵空間(Keyspaces)

鍵空間是Cassandra的數據容器,能夠理解爲關係型數據庫中的數據庫(Database)。對於一個Keyspace來講,有如下幾個屬性:

  • 數據複製節點數目(Replication factor ):定義Keyspace中每行數據的複製節點數目,若是定義爲三,在哈希環上,每行數據將會有三個拷貝節點,而且都可以被客戶端請求到。

  • 複製替換策略(Replica placement strategy):定義在一致性哈希環中某個節點的替換策略。

  • 列族(Column Families):相似於關係型數據庫中的表(Table),是列的容器。

列族(Column Families)

上面已經講到,列族是列的容器,它的結構像是一個四維哈希表:

[Keyspace][ColumnFamily][Key][Column]

若是用JSON表示,一組存放在列族中的數據看起來是這樣的:

Hotel {
    key: AZC_043 { name: Cambria Suites Hayden, phone: 480-444-4444,address: 400 N. Hayden Rd., city: Scottsdale, state: AZ, zip: 85255} 
    key: AZS_011 { name: Clarion Scottsdale Peak, phone: 480-333-3333,address: 3000 N. Scottsdale Rd, city: Scottsdale, state: AZ, zip: 85255} 
    key: CAS_021 { name: W Hotel, phone: 415-222-2222,address: 181 3rd Street, city: San Francisco, state: CA, zip: 94103} 
    key: NYN_042 { name: Waldorf Hotel, phone: 212-555-5555,address: 301 Park Ave, city: New York, state: NY, zip: 10019} }

使用Cassandra建立鍵空間Hotelier,列族爲Hotel,並查詢行鍵(Row Key)爲「NYN_042」的結果顯示:

cassandra> get Hotelier.Hotel['NYN_042']
=> (column=zip, value=10019, timestamp=3894166157031651)
=> (column=state, value=NY, timestamp=3894166157031651)
=> (column=phone, value=212-555-5555, timestamp=3894166157031651)
=> (column=name, value=The Waldorf=Astoria, timestamp=3894166157031651) 
=> (column=city, value=New York, timestamp=3894166157031651)

列(Column)

若是你對「列」的理解來自於關係型數據庫,那麼很容易產生和我以前同樣的誤解,覺得Cassandra是把關係型數據庫的行列進行了某種倒置而獲得的設計。其實不是這樣的,Cassandra的列是一組鍵值對,它的結構以下圖所示(事實上,這個數據結構是Cassandra 0.7.0,最新的2.0.3版本中ByteBuffer替代了byte[],long型的日期時間替代了IClock):

Screen Shot 2013-11-30 at 7.45.30 PM

使用JSON描述的列結構:

{
    "name": "email",
    "value: "me@example.com", 
    "timestamp": 1274654183103300
}

超級列(Super Column)的結構:

Screen Shot 2013-11-30 at 7.55.14 PM

複合鍵(Composite Keys)

有時咱們會遇到不一樣省份可能有一樣的城市名稱,或不一樣的城市有重名的街道,這時使用單一的城市名稱或街道名稱來做爲Key就會沒法識別。Cassandra容許你使用Key1:Key2的結構來存儲一對值做爲Key,一個常見的例子是使用<userid:lastupdate>這樣的結構來存儲用戶ID及最後登陸時間。下面是一個例子:

HotelByCity (CF) Key: city:state {
    key: Phoenix:AZ {AZC_043: -, AZS_011: -} 
    key: San Francisco:CA {CAS_021: -}
    key: New York:NY {NYN_042: -}
}

最後讓咱們來鞏固一下Cassandra和關係型數據庫的區別吧:

  • 沒有查詢語言:No SQL (Structured Query Language);

  • 沒有外鍵約束:關係型數據庫的最重要特徵;

  • 雙重簇索引:在關係型數據庫中,每一個表只能指定一個簇索引,其它的索引查詢都會致使全表掃描,但在Cassandra中,咱們能夠有第二級的簇索引;

  • 排序是在設計時決策:Cassandra不支持Order By,排序是須要設計時考慮,而不是像在關係型數據庫查詢時刻使用Order By;

  • 無數據結構約定:這是Cassandra最大的優點,在關係型數據庫中,咱們設計數據庫結構時老是慎之又慎,但在Cassandra中不須要預先約定數據結構。

本文參考自《Cassandra: The Definitive Guide》

原文連接:Cassandra – 理解關鍵概念和數據模型

相關文章
相關標籤/搜索