cassandra學習筆記4--Cassandra Java客戶端

  現在開始深入瞭解一下cassandra的數據模型。cassandra是一種NoSQL數據庫,NoSQL並不是指沒有SQL語句,而是指No Relationalcassandra的數據模型結合了Dynamokey/valueBigTable
 
的面向列的特點,主要被設計爲存儲大規模的分佈式數據。
     PS:圖片在這裏顯示不全,why?要看圖片,可以另存爲或複製圖片地址,在瀏覽器裏打開。

一、cassandra數據模型的特點

        1.它基於key-value模型

        cassandra的數據庫由ColumnFamilies組成,一個ColumnFamily是一個key-value鍵值對的集合。若和關係型數據庫類比,ColumnFamily相當於表,而裏面的key-value鍵值對相當於表裏的一條記錄。

        2.它的key-value模型有多層嵌套

        ColumnFamily裏的每條記錄都是一個key-value對,value部分存放的是無限制的Columns。每個Column都有一個Column Namevalue,因此Column實際也是一個key-value對。但Columnvalue部分已經是最基本的數據存儲單元,不能再向下嵌套了。在這種嵌套下,ColumnFamily的每條記錄都包含一個key和一個由Columns組成的value(至少有一個Column),也就是說ColumnFamilyvalue只是一箇中間人,實際存儲數據的是value裏的Columns。如下圖所示。


        上面所說的是雙層嵌套,還有一種三層嵌套。在這種情況下,ColumnFamily每條記錄的value部分不是Columns,而是一種被稱爲SuperColumn的結構。SuperColumnkeySuperColumn name,它的value部分可以存儲多個Columns,如下圖所示:


        這樣就有以下三種嵌套:

[java] view plaincopy
  1. ColumnFamily: key - value(SuperColumn)  
  2. SuperColumn: key(SuperColumn name) - value(Column)  
  3. Column: key(Column name) - value  

        SuperColumn裏不能再存儲SuperColumn,因此cassandra的嵌套最多爲三層。

        3.ColumnSuperColumnname部分都可以用來存儲實際數據

        首先,它們的name部分可以用來當做屬性名。比如在一個存儲用戶郵箱的記錄裏,它是這樣的:

[java] view plaincopy
  1. Column name=Email,value="[email protected]";  

        這是我們在傳統關係型數據庫裏所習慣和使用的。但在cassandra裏,name部分也可以直接用來存儲實際數據。比如在一個只用來存儲用戶郵箱的記錄裏,我們可以這樣:

[java] view plaincopy
  1. Column name="[email protected]",value=null;  

        這得益於(a)cassandra的非結構化數據存儲,數據的存儲不需要固定的位置(b)name部分也是使用字節流存儲(關係型數據庫的字段名必須是字符),因此可以存儲任何類型的數據。

        4.ColumnSuperColumn按照name的順序存儲

        需要注意的是,cassandra並不是按照value的順序存儲數據,而是按照name。關於這點下文會詳細說明。

二、cassandra數據模型的構成

        在這一部分,將詳細講解cassandra數據模型的各個組成部分。

        1.Column

        Column是數據存儲的最小單位。它是一個包括namevaluetimestamp(時間戳)的元祖。下面是一個Column的示例:

[java] view plaincopy
  1. {  
  2.     name:"age",  
  3.     value:24,  
  4.     timestamp:123456789  
  5. }  

        方便書寫,後文將省略時間戳,我們將Column看成一個name-value對。namevalue都是字節流,長度沒有限制。

        2.SuperColumn

        一個SuperColumn是一個真正的name-value對,它沒有時間戳。而且它的value部分可以包含無限個Column並且用Columnname部分作爲關鍵字。下面是一個SuperColumn的示例:

[java] view plaincopy
  1. {  
  2.     name:"homeAddress"  
  3.     //value部分是多個Columns  
  4.     value:  
  5.     //這裏的key是Column的name部分  
  6.     street:{name:"street",value:"XiTuCheng road"},  
  7.     city:{name:"city",value:"BeiJing"},  
  8.     zip:{name:"zip",value:"410083"},  
  9. }  

        在後面,不再寫出namevalue,上文將簡寫爲:

[java] view plaincopy
  1. homeAddress:{  
  2.     street:"XiTuCheng road",  
  3.     city:"BeiJing",  
  4.     zip:"410083",  
  5. }  

        3.Row

        在介紹下文的ColumnFamily前,我們先熟悉一下Row。在cassandra裏,每個ColumnFamily都存在一個單獨的文件裏,這個文件以Row爲單位存儲並排序。因此,我們應儘量將相關的Column放在同一個ColumnFamily裏。

        ColumnFamily的組成是一行行的Row,一個Row就是一個key-value對,key決定數據將被存在哪臺機器上(筆記二的token部分有解釋),value部分就是ColumnsSuperColumns

        4.ColumnFamily

        ColumnFamily是一個可以包含無數個Row的結構,又因爲Rowvalue部分是ColumnsSuperColumns,因此ColumnFamily實際是ColumnsSuperColumns的容器。ColumnFamily對應關係型數據庫裏的“表”。下面給出ColumnFamilyRow的一個簡單示例(使用Column):

[java] view plaincopy
  1. User={//這是一個ColumnFamily,名字是User  
  2.     zhangsan:{//這是一個Row,Row的key是zhangsan  
  3.     //下面的value可以有無限制的Columns,這裏有兩個  
  4.         username:"zhangsan",  
  5.         email:"[email protected]",  
  6.     },//這個Row結束了  
  7.     lisi:{//這是第二個Row,Row的key是lisi  
  8.     //value部分,依然是Columns,lisi有三個  
  9.         username:"lisi",  
  10.         email:"[email protected]",  
  11.         phone:"123456"  
  12.     },//Row結束  
  13. }  

        又如下圖所示:


        在這個層面沒有設計模式的要求,Row沒有預先定義它們應該包含的Columns列表,就如上面的示例,李四可以隨意的多一個phoneColumn。一個Row可能有成千上萬個Columns而另一個Row可能只有一個Columncassandra在這一點上有無法比擬的靈活性。

        5.屬性爲SuperColumnFamily

        上面的示例是一個type爲標準的(StandardColumnFamily,另外也有SuperColumnFamily,這取決於我們創建ColumnFamily時的定義。顧名思義,一個類型爲SuperColumnFamilyRow存儲的不是Columns,而是SuperColumns。在這種情況下,一個Rowvalue部分有若干個SuperColumns,一個SuperColumnsvalue部分又有若干個Columns。如下圖所示:


        爲什麼要有SuperColumn呢?SuperColumn提供了比普通Column多一級的一對多關係。Column只能讓一個key存儲一組相關聯的Columns,而這個能讓一個key存儲多組相關聯的Columns

        這裏給出一個應用:假設我們提供一種網上地址本的服務,用戶可以在這保存他的朋友們的地址,而地址又是由不同的屬性如郵編、街道、城市等組成。這時候我們可以採用SuperColumn。對於ColumnFamily,它的key使用的是用戶自己的名字,value部分是若干SuperColumns。每個SuperColumnsname部分是用戶某個朋友的名字,value部分是若干Columns,存儲地址的各個屬性。下面是示例:

[java] view plaincopy
  1. AddressBook={//這是一個SuperColumnFamily,名字是AddressBook  
  2.       
  3.     zhangsan:{//這是一個Row,key是zhangsan,張三的地址本  
  4.     //下面是Row的Value部分,可以有任意個SuperColumns  
  5.         lisi:{//這是SuperColumn的name  
  6.             //下面是Columns,表示地址  
  7.             street:"XiTuCheng road",  
  8.             zip:"410083",  
  9.             city:"BeiJing"  
  10.         },  
  11.         wangwu:{//另一個SuperColumn  
  12.             street:"XiTuCheng road",  
  13.             zip:"410083",  
  14.             city:"BeiJing"  
  15.         },  
  16.         zhaoliu:{//SuperColumn  
  17.             street:"XiTuCheng road",  
  18.             zip:"410083",  
  19.             city:"BeiJing"  
  20.         },  
  21.         .......  
  22.     }//end the row of zhangsan  
  23.       
  24.     lisi:{//這是另一個Row,key是lisi,李四的地址本  
  25.         wangwu:{//SuperColumn  
  26.             street:"XiTuCheng road",  
  27.             zip:"410083",  
  28.             city:"BeiJing"  
  29.         },  
  30.         zhangsan:{//SuperColumn  
  31.             street:"XiTuCheng road",  
  32.             zip:"410083",  
  33.             city:"BeiJing"  
  34.         },  
  35.         .......  
  36.     }  
  37. }  

        6.KeySpace

        KeySpace是最外層的容器,也是最大的容器,通常一個應用程序對應一個KeySpace。所有的ColumnFamily都位於一個KeySpace裏面,它相當於關係數據庫裏的DB

三、cassandra的數據排序

        前面所介紹的是cassandra裏各種數據容器的概念,現在來看看數據模型的另外一個關鍵地方即數據是如何排序的。cassandra和關係型數據庫不同,你無法在取出數據時指定一種排序(order by)。數據在你存儲到集羣,被寫入數據庫時已經按照預定的規則被排好序。當你取出數據時,它們的順序已經確定了。

        如前問所說,cassandra是按照name而不是value進行排序。cassandra在寫入數據的時候,每個row中的所有Columns會按照name自動排好序。排序的規則由ColumnFamilyCompareWith選項確定,可選的有:BytesTypeUTF8TypeLexicalUUIDTypeTimeUUIDTypeAsciiTypeLongType。這些選項將Column Name看作不同的數據類型來排序,如LongType將它視爲64bit Long類型。如下面給出的例子:

[java] view plaincopy
  1. {name: 123, value: “hello there”},  
  2. {name: 832416, value: “kjjkbcjkcbbd”},  
  3. {name: 3, value: “101010101010″},  
  4. {name: 976, value: “kjjkbcjkcbbd”}  

        採用LongType排序類型,結果是:

[java] view plaincopy
  1. {name: 3, value: “101010101010″},  
  2. {name: 123, value: “hello there”},  
  3. {name: 976, value: “kjjkbcjkcbbd”},  
  4. {name: 832416, value: “kjjkbcjkcbbd”}  

        採用UTF8Type排序類型,結果是:

[java] view plaincopy
  1. {name: 123, value: “hello there”},  
  2. {name: 3, value: “101010101010″},  
  3. {name: 832416, value: “kjjkbcjkcbbd”},  
  4. {name: 976, value: “kjjkbcjkcbbd”}  

        這些排序規則也適用於SuperColumnsRow內的排序,但對於SuperColumn內的Columns,用來定義排序規則的參數不再是RowSuperColumn裏的CompareWith,而是CompareSubcolumnsWith

        我們可以自定義排序規則,實現接口org.apache.cassandra.db.marsha1.IType即可。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章