読者です 読者をやめる 読者になる 読者になる

プログラマでありたい

おっさんになっても、プログラマでありつづけたい

Cassandraのデータモデリング。或いはKeyspaceの設定方法

分散DB

 ドキュメントにはサラッとしか書かれていないので、ちょっと解りにくいCassandraのデータ構造及び設定方法です。
公式ドキュメントの致命的な欠点で、データモデルのイメージ図がないので作ってみました。

Cassandraのデータモデル - DenkiYagiさんの素晴らしいモデル図を写させて貰いました。)

KeySpace

まずCassandraのデータ構造で一番大きな括りに、keyspaceがあります。RDBに例えると(怒られそうですが)、スキーマやデータベースにあたります。

ColumnFamily

 ColumnFamilyは、テーブルに当たるものです。重要な点ですが、keypaceとColumnFamilyは、conf/storage-conf.xmlに定義されています。また現時点では、confの内容をシステムに反映させるにはシステムのリスタートが必要になります。

Key & Row

 ColumnFamilyの中に複数のKeyとRowがあります。Cassandraのデータの取得は、基本的にこのKeyを介して行われます。オブジェクト識別子(OID)のようなものです。Rowの中に実データを格納します。

Column & name,value

 Rowの中にColumnがあります。また一つのRowで複数のカラムが格納可能です。Columnの構成はシンプルで、name,valueとtimestampで構成されています。nameとvalueはbinary型なので、基本何でもいれちゃえます。また面白いことにtimestampの時間は、クライアント型のtimestampを設定します。なので、サーバ側とちゃんと時間同期しておいてくださいねとのことです。思い切った割り切りですね。分散型DBってこんな感じなのでしょうか。

Super Column

 複数のカラムを一つのnameでまとめた、Super Columnというのも設定可能です。これは同じ意味をもつデータ群をまとめておけば便利でしょうね。


 以下、デフォルトの設定です。
基本的な書き方は網羅しているので、参考になります。
KeyspaceとColumnFamilyを設定しておく必要があります。
またキャッシュの戦略や比率、値の並び順等の設定も出来ます。
この辺りは、また掘り下げて調べてみます。

  <!--
   ~ Keyspaces and ColumnFamilies:
   ~ A ColumnFamily is the Cassandra concept closest to a relational
   ~ table.  Keyspaces are separate groups of ColumnFamilies.  Except in
   ~ very unusual circumstances you will have one Keyspace per application.

   ~ There is an implicit keyspace named 'system' for Cassandra internals.
  -->
  <Keyspaces>
    <Keyspace Name="Keyspace1">
      <!--
       ~ ColumnFamily definitions have one required attribute (Name)
       ~ and several optional ones.
       ~
       ~ The CompareWith attribute tells Cassandra how to sort the columns
       ~ for slicing operations.  The default is BytesType, which is a
       ~ straightforward lexical comparison of the bytes in each column.
       ~ Other options are AsciiType, UTF8Type, LexicalUUIDType, TimeUUIDType,
       ~ and LongType.  You can also specify the fully-qualified class
       ~ name to a class of your choice extending
       ~ org.apache.cassandra.db.marshal.AbstractType.
       ~
       ~ SuperColumns have a similar CompareSubcolumnsWith attribute.
       ~
       ~ BytesType: Simple sort by byte value.  No validation is performed.
       ~ AsciiType: Like BytesType, but validates that the input can be
       ~            parsed as US-ASCII.
       ~ UTF8Type: A string encoded as UTF8
       ~ LongType: A 64bit long
       ~ LexicalUUIDType: A 128bit UUID, compared lexically (by byte value)
       ~ TimeUUIDType: a 128bit version 1 UUID, compared by timestamp
       ~
       ~ (To get the closest approximation to 0.3-style supercolumns, you
       ~ would use CompareWith=UTF8Type CompareSubcolumnsWith=LongType.)
       ~
       ~ An optional `Comment` attribute may be used to attach additional
       ~ human-readable information about the column family to its definition.
       ~
       ~ The optional KeysCached attribute specifies
       ~ the number of keys per sstable whose locations we keep in
       ~ memory in "mostly LRU" order.  (JUST the key locations, NOT any
       ~ column values.) Specify a fraction (value less than 1), a percentage
       ~ (ending in a % sign) or an absolute number of keys to cache.
       ~ KeysCached defaults to 200000 keys.
       ~
       ~ The optional RowsCached attribute specifies the number of rows
       ~ whose entire contents we cache in memory. Do not use this on
       ~ ColumnFamilies with large rows, or ColumnFamilies with high write:read
       ~ ratios. Specify a fraction (value less than 1), a percentage (ending in
       ~ a % sign) or an absolute number of rows to cache.
       ~ RowsCached defaults to 0, i.e., row cache is off by default.
       ~
       ~ Remember, when using caches as a percentage, they WILL grow with
       ~ your data set!
      -->
      <ColumnFamily Name="Standard1" CompareWith="BytesType"/>
      <ColumnFamily Name="Standard2"
                    CompareWith="UTF8Type"
                    KeysCached="100%"/>
      <ColumnFamily Name="StandardByUUID1" CompareWith="TimeUUIDType" />
      <ColumnFamily Name="Super1"
                    ColumnType="Super"
                    CompareWith="BytesType"
                    CompareSubcolumnsWith="BytesType" />
      <ColumnFamily Name="Super2"
                    ColumnType="Super"
                    CompareWith="UTF8Type"
                    CompareSubcolumnsWith="UTF8Type"
                    RowsCached="10000"
                    KeysCached="50%"
                    Comment="A column family with supercolumns, whose column and subcolumn names are UTF8 strings"/>

      <!--
       ~ Strategy: Setting this to the class that implements
       ~ IReplicaPlacementStrategy will change the way the node picker works.
       ~ Out of the box, Cassandra provides
       ~ org.apache.cassandra.locator.RackUnawareStrategy and
       ~ org.apache.cassandra.locator.RackAwareStrategy (place one replica in
       ~ a different datacenter, and the others on different racks in the same
       ~ one.)
      -->
      <ReplicaPlacementStrategy>org.apache.cassandra.locator.RackUnawareStrategy</ReplicaPlacementStrategy>

      <!-- Number of replicas of the data -->
      <ReplicationFactor>1</ReplicationFactor>

      <!--
       ~ EndPointSnitch: Setting this to the class that implements
       ~ AbstractEndpointSnitch, which lets Cassandra know enough


参考:
DataModel - Cassandra Wiki
Cassandraのデータモデル - DenkiYagi



Apache Cassandraの使い方目次