S-JIS[2010-05-09/2010-10-21] 変更履歴

Apache Cassandra

Cassandra(カサンドラ)は、AmazonのDynamoとGoogleのBigTableを元にしたオープンソースの列指向分散データベース。(リレーショナルデータベース(RDB)ではない)
Javaで作られているが、Thriftベースなので他の言語からもアクセスしやすいらしい。

Dynamoの分散システム設計とBigTableのデータモデル(ColumnFamily)を参考にしており、単なるkey/valueストアより高機能らしい。


WindowsXPへのインストール

まず、JDK1.6をインストールしておく。

  1. 公式ページの上の方の 「Download」をクリックして、最新版のダウンロードページを開く。
  2. アーカイブファイル名(apache-cassandra-0.6.1-bin.tar.gz)をクリックしてミラーページを開く。
  3. ミラーページから適当なリンクをクリックしてダウンロードする。
  4. ダウンロードしたファイルを適当な場所に解凍する。(例:C:\apache-cassandra-0.6.1)
  5. 環境変数CASSANDRA_HOME設定しておく。
    ついでに、環境変数JAVA_HOMEも設定されていなければ設定しておく。
    CASSANDRA_HOME C:\apache-cassandra-0.6.1
    JAVA_HOME C:\Program Files\Java\jdk1.6.0_20

ソースはapache-cassandra-0.6.1-src.tar.gzをダウンロードし、解凍する。
Eclipseのソースの添付では、CASSANDRA_HOME/lib/apache-cassandra-0.6.1.jarに対してapache-cassandra-0.6.1-src/src/javaのフォルダーを指定する。
が、部分的に足りないものがあるので、多少加工する必要がある。[2010-05-11]


WindowsXPでの動作確認

  作業内容 実施コマンド 備考
1 Cassandraを起動する。
%CASSANDRA_HOME%\bin\cassandra.bat
Starting Cassandra Server
Listening for transport dt_socket at address: 8888
 INFO 16:41:47,484 Auto DiskAccessMode determined to be standard
 INFO 16:41:48,781 Saved Token not found. Using 104579272340175537742052921992137159771
 INFO 16:41:48,781 Saved ClusterName not found. Using Test Cluster
 INFO 16:41:48,906 Creating new commitlog segment /var/lib/cassandra/commitlog\CommitLog-1273390908906.log
 INFO 16:41:49,203 Starting up server gossip
 INFO 16:41:49,484 Binding thrift service to localhost/127.0.0.1:9160
 INFO 16:41:49,546 Cassandra starting up...
cassandra.batをダブルクリックして実行すればよい。
コンソールは開きっぱなしにしておくこと。
デバッグ接続用ポート:8888
Thriftによる接続ポート:9160
で起動する。
DBの実体は「C:\var\lib\〜」
ログファイルは「C:\var\log\〜」
に出力される(勝手に作られる)。
2 cassandra CLIを起動する。
%CASSANDRA_HOME%\bin\cassandra-cli.bat
Starting Cassandra Client
Welcome to cassandra CLI.

Type 'help' or '?' for help. Type 'quit' or 'exit' to quit.
cassandra>
Cassandraの対話型ツール。
  CLIでちょっと動作確認
cassandra> connect localhost/9160
Connected to: "Test Cluster" on localhost/9160
cassandra> show keyspaces
Keyspace1
system
 
3 CLIを終了する。
cassandra> exit
 
4 Cassandraを停止する。   Cassandraのコンソールを終了させるだけ。
(停止用のバッチファイルは特に無い)

あと、JMXの為にポート8080を使っているようなので、他のアプリ(Tomcatとか)で8080を使っている場合はどちらかを変える必要がある。
Cassandra側を変えるなら、CASSANDRA_HOME/bin/cassandra.batを修正する。

 -Dcom.sun.management.jmxremote.port=8080^

Cassandraのテーブルの基礎

Cassandraの用語は、似たようなkey/valueストアであるHBaseとも微妙に違ってややこしい(苦笑)

キースペース(Keyspace)

まずキースペースについて。
Cassandraでは、1つのキースペース内に複数のColumnFamilyを持つ。
HBaseではテーブルがColumnFamilyを持つのであって、Cassandraのキースペースに当たるものは無い)
Cassandraのデータモデルの説明によれば、キースペースは、RDBで言うところのスキーマやDB(テーブルの集合)に当たるものらしい。
したがってキースペースは概ね1アプリケーションにつき1つらしいので、HBaseとは考え方が違うようだ。

キースペースはstorage-conf.xmlのKeyspace要素で定義する。
キースペース名は文字列(String)。

カラムファミリー(Column Family)

キースペース内に複数のカラムファミリーを持つ。キースペースがRDBで言うところのDBなので、カラムファミリーはテーブルということになる。
HBaseではテーブルがColumnFamilyを持つので、位置付けが異なる。
いずれにしても「カラムファミリー名」を持ち、その名前でデータを保持することに変わりはない。

カラムファミリーは事前に定義しておく必要がある。→storage-conf.xmlのColumnFamily要素
カラムファミリーはスーパーカラムを持つかどうかで2種類に分けられる。
スーパーカラムを持たないのがColumnFamily(CF)、スーパーカラムを持つカラムファミリーはSCF(ColumnFamily of type "Super")と呼ばれることがある。

したがってカラムファミリーは、「カラムファミリー名」をキーとし、「スーパーカラムまたはカラム」を値とするマップといった感じになる。
カラムファミリー名は文字列(String)。

スーパーカラム(Super Column)

Cassandraでは、通常のカラムをグルーピングする層が作れる。それがスーパーカラム。
この機能はHBase(やRDB)には無い。

「スーパーカラム名」をキーとし、「カラム」を値とするマップのような位置付けになる。
スーパーカラム名は実行時(データ登録時)に好きなように付けられる。
スーパーカラム名はバイト列(byte[])。通常は文字列をUTF-8にしたもの。

スーパーカラムは有っても無くてもいいので、「Cassandraは4次元または5次元のデータ構造」と言っているのだろう。
(スーパーカラムを使う場合は5次元、使わない場合は4次元)
カラムファミリーがスーパーカラムを持つかどうかはカラムファミリーの定義で指定する。

カラム(Column)

Columnは、Cassandraの最小データ単位。
“カラム”という名前ではあるが、RDBの列名相当ではなく(カラム名だけを指すのではなく)、データ値を保持する構造体
Column構造体は、カラム名(RDBのカラム名・列名に相当)・データ値・タイムスタンプを持つ。

カラム名は実行時(データ登録時)に好きなように付けられる。
カラム名はバイト列(byte[])。通常は文字列をUTF-8にしたもの。
値はバイト列(byte[])。文字列を扱う場合、通常はUTF-8を使う。
タイムスタンプは64ビットの整数値(long)。

データモデルの説明によると、タイムスタンプに登録する時刻 の値を決めるのは、クライアントアプリの責任。[2010-03-10]
つまり複数のマシンからDB更新を行う際に、マシン毎の日時の整合性が取れていないと とんでもない事になる可能性がある訳だ。
ちなみに、タイムスタンプはマイクロ秒単位にしておくのが無難。(CLIのsetコマンドでデータを登録するとマイクロ秒単位になるから)
(マイクロ秒で扱っても、西暦294247年までは大丈夫(笑))

Columnは HBaseのCellに相当すると思うが、Cellではカラム名を持っていない。
また、Cellはタイムスタンプと共にデータを履歴管理している。
Cassandra内部でもタイムスタンプを使ってデータの履歴管理がされていると思うが、HBaseと違って履歴そのものを(過去のデータを明示的に)取得することは出来ないようだ。

行(Row)

行は、レコードに相当するもの(これはRDBもHBaseも同じ)。レコードの識別はキー(Key)によって行う。
キーは文字列(String)。

レコードを取得すると、カラムのリスト(List<Column>、厳密に言うとList<ColumnOrSuperColumn>)が返ってくる。
(HBaseでは、カラム名をキーとし、Cellを値とした(キーでソートされた)マップが返ってくる)


cassandra CLIを使ったデータアクセスは、以下のような感じになる。
Keyspace1は、Cassandraをインストールした直後のデフォルト状態で入っているキースペース
 Standard1Standard2通常のカラムファミリーSuper1Super2スーパーカラムを持つカラムファミリー

cassandra> set Keyspace1.Standard2['jsmith']['first'] = 'John'
Value inserted.
cassandra> set Keyspace1.Standard2['jsmith']['last'] = 'Smith'
Value inserted.
cassandra> set Keyspace1.Standard2['jsmith']['age'] = '42'
Value inserted.

cassandra> get Keyspace1.Standard2['jsmith']
=> (column=last, value=Smith, timestamp=1273401786421000)
=> (column=first, value=John, timestamp=1273401776968000)
=> (column=age, value=42, timestamp=1273401792781000)
Returned 3 results.
cassandra> set Keyspace1.Super1['jsmith']['name']['first'] = 'John'
Value inserted.
cassandra> set Keyspace1.Super1['jsmith']['name']['last'] = 'Smith'
Value inserted.
cassandra> set Keyspace1.Super1['jsmith']['attr']['age'] = '42'
Value inserted.

cassandra> get Keyspace1.Super1['jsmith']
=> (super_column=6e616d65,
     (column=6669727374, value=John, timestamp=1273401380984000)
     (column=6c617374, value=Smith, timestamp=1273401712765000))
=> (super_column=61747472,
     (column=616765, value=42, timestamp=1273401719343000))
Returned 2 results.
  キースペース カラムファミリー キー スーパーカラム カラム
例1 Keyspace1 Standard2 jsmith   first John
Keyspace1 Standard2 jsmith   last Smith
Keyspace1 Standard2 jsmith   age 42
次元数 1 2 3   4  
例2 Keyspace1 Super1 jsmith name first John
Keyspace1 Super1 jsmith name last Smith
Keyspace1 Super1 jsmith attr age 42
次元数 1 2 3 4 5  

要するに4次元配列(あるいは5次元配列)を扱っているのと同じイメージ。


CassandraとThriftの関係

Cassandraの実装(クライアントとの通信)は、Thrift(スリフト)をベースに作られているらしい。[2010-03-11]

Thriftは、RPC(リモートプロシージャーコール)を扱うフレームワークらしい。
RPCとは、サーバーで動いているプログラムのプロシージャー(関数・メソッド)をリモートで(ネットワーク経由で)呼び出すこと。
となるとサーバーアプリとそれを呼び出すクライアントアプリ、および受け渡すデータ構造(構造体)が必要になるが、Thriftを使うと、それらのプログラム(の雛形)を生成できる。
しかもThriftに対応している言語なら何でもいい。JavaとかC++とかC#とかPerlとか。

Cassandraのサーバープログラム(クライアントとの通信部分)はThriftを使って生成されているので、Thriftサーバーとして動く。
つまりThriftで生成されたクライアントアプリであれば、(Cassandra本体はJavaだが、)どの言語からでもアクセスできる。
cassandra CLIは、Javaで作られたThriftクライアントアプリということになる。

JavaでCassandraにアクセスするコーディング例


Java目次へ行く / HBaseへ行く / 技術メモへ戻る
メールの送信先:ひしだま