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)。
但問題是,除非咱們記錄了每一個值的存放地址,咱們將沒法訪問到這些數據,這看起來很像一個數組或集合,咱們必須記住某個值的索引號,而且還要預先定義好這個數組的寬度,不然它會沒法容納足夠多的數據。
解決辦法是爲每一個數據添加一個惟一名稱(Name),只要咱們記住了這個名稱,就能找到這個數據了,這樣,咱們就有了一堆名稱——值對(Name/Value Pair)。
這個結構很像哈希表,能夠知足一些信息的存儲,例如用戶的基本信息,姓、名、電話、手機、公司、地址等,而且咱們能夠根據須要來決定存儲哪些名稱和值,如此,咱們就獲得了一個單獨的行(Single Row),並引出了Cassandra數據庫中重要的行列概念定義:
一組包含名稱值對的數據叫作行(Row),而每一組名稱值對(Name/Value Pair)被稱之爲列(Column)。
在關係型數據庫中,列的名稱必須是字符串,但在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),你能夠往超級列中添加子列。
鍵空間(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):
使用JSON描述的列結構:
{ "name": "email", "value: "me@example.com", "timestamp": 1274654183103300 }
超級列(Super Column)的結構:
複合鍵(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》