前面的文章已經有稍微提到 Keyspace,院長把 keyspace 想像成 RDBMS 中的 database,而 database 的階層就像這樣「database」→「table」→「columns」,當然 keyspace 也有相對應的階層「keyspace」→「column family」→「column, super column」,所以在設計 keyspace 就像在設計 database 一樣。
要開始設計 keyspace 之前,當然要先了解 keyspace,接下來就要帶大家來了解 keyspace
Keyspace 的組成
剛剛有說過了 keyspcae 就像是 database 一樣,當然也會有 schema 去描述 keyspace,而這份 schema 是儲存在「conf/storage-conf.xml」裡面,就讓我們將這個檔打開,找到「<Keyspaces>」標籤的地方,其中有一些註解說明,這裡院長就把他去掉了,應該可以看到以下的 XML 設定。
<Keyspaces> <Keyspace Name="Keyspace1"> <KeysCachedFraction>0.01</KeysCachedFraction> <ColumnFamily CompareWith="BytesType" Name="Standard1"/> <ColumnFamily CompareWith="UTF8Type" Name="Standard2"/> <ColumnFamily CompareWith="TimeUUIDType" Name="StandardByUUID1"/> <ColumnFamily ColumnType="Super" CompareWith="UTF8Type" CompareSubcolumnsWith="UTF8Type" Name="Super1" Comment="A column family with supercolumns, whose column and subcolumn names are UTF8 strings"/> </Keyspace> </Keyspaces>
<Keyspaces>
所有的 Keyspace 都要放在 Keyspaces 標籤底下。
內容值
-
<Keyspace>
<Keyspace>
定義 keyspace 的標籤
內容值
-
<KeysCachedFraction>
-
<ColumnFamily>
必要屬性
- Name
- 代表這個 keyspace 的名稱,這是唯一值不能與其他的 keyspace 衝到
<ColumnFamily>
定義 column family
必要屬性
- CompareWith
- 排序比較原則
- Name
- column family 的名稱,在同一個 keyspace 中不能重複
其他屬性
- ColumnType
- 欄位的型態,如果標籤沒特別指定 ColumnType 的話,就是 Standard 型態,有指定「Super」的話就表示是 Super 型態。 Standard 型態只能存 column;Super 型態只能存 super column。
- CompareSubcolumnsWith
- 如果指定了「Super」型態,就必須定義 super column 底下的 column 採用的排序比較原則
- Comment
- column family 的註解
CompareWith
排序比較原則有以下六種,而比較的單元是 column name,假設有三個人名「ian」、「john」、「charles」。
- BytesType
- 以 byte 的方式來比較,上述的例子就會排成:charles、ian、 john 。
- AsciiType
- 跟 byte 的方式一樣,不過 column name 必須要能夠轉成US-ASCII
- UTF8Type
- 轉成 UTF8 來比較
- LongType
- 以長度來比較,上述的例子就會排成:ian、 john 、charles。
- LexicalUUIDType
- 使用 128bit 的 UUID 來比較
- TimeUUIDType
基本上「BytesType」、「AsciiType」、「UTF8Type」都屬於文字比較,差異的部份就是在於比較的方式。「LongType」是根據文字長度來比較。「LexicalUUIDType」、「TimeUUIDType」比較的方式就是根據 UUID 來進行比較。
要特別注意的是,因為 CompareWith 會拿 column name 來作比較,所以 column name 也要符合這些 type 的格式。
- 「BytesType」、「AsciiType」、「UTF8Type」必須要是「String Bytes」的格式
- 「LongType」必須要是「Long Bytes」的格式
- 「LexicalUUIDType」、「TimeUUIDType」必須要是「UUID Bytes」的格式
其中 Cassandra CLI 可以支援「BytesType」、「AsciiType」、「UTF8Type」的寫入,其他「LongType」、「LexicalUUIDType」、「TimeUUIDType」必須透過 Apache Thrift才能將 column 寫入,這部份就留到後面的文章再來詳細解釋。
下面我们看twitter的Schema:
<Keyspace Name="Twitter">
<ColumnFamily CompareWith="UTF8Type" Name="Statuses" />
<ColumnFamily CompareWith="UTF8Type" Name="StatusAudits" />
<ColumnFamily CompareWith="UTF8Type" Name="StatusRelationships"
CompareSubcolumnsWith="TimeUUIDType" ColumnType="Super" />
<ColumnFamily CompareWith="UTF8Type" Name="Users" />
<ColumnFamily CompareWith="UTF8Type" Name="UserRelationships"
CompareSubcolumnsWith="TimeUUIDType" ColumnType="Super" />
</Keyspace>
我们看到一个叫Twitter的keyspace,包含若干个CF,其中StatusRelationships和 UserRelationships被定义为包含Super column的CF,CompareWith定义了column的排序规则,CompareSubcolumnsWith定义了subcolumn的排序 规则,这里使用了两种:TimeUUIDType和UTF8Type。我们没有看到任何有关column的定义,这意味着column是可以灵活变更的。
Users CF记录用户的信息,Statuses CF记录tweets的内容,StatusRelationships CF记录用户看到的tweets,UserRelationships CF记录用户看到的followers。我们注意到排序方式是TimeUUIDType,这个类型是按照时间进行排序的UUID字段,column name是用UUID函数产生(这个函数返回了一个UUID,这个UUID反映了当前的时间,可以根据这个UUID来排序,有点类似于timestamp 一样),所以得到结果是按照时间来排序的。使用过twitter的人都知道,你总是可以看到自己最新的tweets或者最新的friends.