前回はCassandraのデータモデルについて説明しました。今回は実際にデータ設定とJavaコードからCassandraにアクセスする基本を見ていきます。コードはEclipseで書くことを前提に進めていきます。
Cassandraの設定で最低限必要な3つの項目
Cassandraの設定はすべてconf/storage-conf.xmlに記述されます。今回は、まずはじめてみるために必要最小限な項目の設定を行いましょう。
設定が必要なのは以下の項目になります。
- ① キースペース、カラムファミリの設定
- ColumnType属性
- CompareWith属性
- CompareSubcolumnsWith属性
- ② コミットログとデータディレクトリを設定する
- ③ ノードを設定する
キースペース、カラムファミリを設定する
何はともあれ、キースペースとカラムファミリを指定しないとデータを格納すらできません。設定は、たとえば以下のようになります。
Name属性は見たとおりなので割愛します。ColumnFamilyには、Name属性のほかにいくつか知っておかないといけない設定項目があります。
ColumnFamilyで設定すべき属性は、おもに以下の3つです。
ColumnType属性
前回説明したとおり、ColumnFamilyにはカラムだけが含まれるケースと、スーパーカラムだけが含まれるケースの2パターンがあります。どちらのケースかは、このColumnType属性で区別します。
上記の例では、次のように分かれます。
- "Standard1"という名前のColumnFamily
→カラムだけが含まれるカラムファミリ
- "Super1"という名前のColumnFamily
→ColumnTypeに"Super"と指定があるので、スーパーカラムだけが含まれるカラムファミリ
ColumnType属性はStandardまたはSuperのどちらかを選択できます。ColumnType属性に何も記載がないとStandardになります。
表1 ColumnType属性の種別
ColumnType設定項目 | 説明 |
Standard | カラムファミリ内にカラムが含まれる |
Super | カラムファミリ内にスーパーカラムが含まれる |
CompareWith属性
次に目につく設定がCompareWithです。これは検索時のカラムのソートのための設定項目です。検索実行時にこのCompareWithで指定されたクラスを使ってカラムがソートされ、結果が返されます。
CompareWith設定には、以下の表(CompareWithの設定種別)のようなオプションが標準であります。CompareWith属性に何も指定しないとBytesTypeが適用されます。
表2 CompareWithの設定種別
CompareWith設定項目 | 説明 |
BytesType | byte[]で比較する。値の検証はしない。 |
UTF8Type | UTF8でも文字列比較をする。 |
AsciiType | byte[]での比較に加えてUS-ASCIIでのエンコードの検証をする。 |
LongType | 64ビット長のlong値で比較する。 |
LexicalUUIDType | 128ビット長UUIDのbyte[]値を比較する。 |
TimeUUIDType | 128ビット長UUIDのタイムスタンプを比較する。 |
具体例を見てみましょう。以下の例ではUTF-8でカラムをソートします。
イメージとしては以下のようになります。カラム名がUTF-8順にソートされます。
SuperColumn:utf8Order |
key | Column |
hoge | name | value | timestamp |
111 | 222 | 1273285360339 |
aaa | value | 1273285360339 |
name | shinpei | 1273285360339 |
こんにちは | さようなら | 1273285360339 |
CompareSubcolumnsWith属性
CompareSubcolumnsWith属性は、スーパーカラムの場合(ColumnType="Super")に使用します。それ以外のケースでは使えません。
スーパーカラムの場合、
- スーパーカラムのソート
→CompareWith
- スーパーカラム内のカラムのソート
→CompareSubcolumnsWith
という形で使い分けます。指定できる項目はCompareWithと同様です。
具体例を見てみましょう。
この例ではCompareWithに"LongType"、CompareSubcolumnsWithに"UTF8Type"を指定しているので、スーパーカラムはLong値でソートされ、スーパーカラム内のカラムはUTF8でソートされます。
以下のようなイメージになります。
ColumnFamily:time_utf8Order |
key | SuperColumn |
hoge | key | Column |
1273284729294 | name | value | timestamp |
moge | aaa | 1273284729294 |
muga | bbb | 1273284729294 |
1273284729347 | name | value | timestamp |
moge | ccc | 1273284729347 |
muga | ddd | 1273284729347 |
キースペース、カラムファミリの設定は以上です。
他にも、レプリケーション数やレプリケーションをどのように行うかなどの指定がありますが、今回は割愛します。
コミットログとデータディレクトリを設定する
次はコミットログとデータディレクトリの設定を行います。
Cassandraは、書き込み時には操作をすべてコミットログに追加で書き込んでいき、その実体(Memtableといいます)はメモリ上にカラムファミリごとに展開していく仕組みになっています。Memtableはサイズの閾値等をもっており、その閾値に達するとディスクに書き出します。この操作のことを「フラッシュ」といい、ディスクに書き出す構造のことを「SSTable」といいます。SSTableは一度書き出されるとその内容は不変で、実際の物理データとしては以下の3つがセットで書き出されます。
インデックスとブルームフィルタは読み込みを高速化するための仕組みです(本連載で今後分量の都合がつけば詳しくご説明します)。
このような内部構造をもっているため、Cassandraではコミットログの書き込むディレクトリと実際のデータを各ディレクトリを明確に分離しておくのが望ましいです。
コミットログはCommitLogDirectoryで設定します。一方、SSTableを永続化する実データ部分はDataFileDirectoryで設定します。DataFileDirectoryは複数設定することが可能です。
設定例としては以下のようになります。
ノードを設定する
最後はノードの設定です。
Cassandraはマスターノードを持たないアーキテクチャのため、特定のノードをマスター指定したりする必要がありません。そのため、ノードの設定は非常に簡潔になっています。
単一ノードで動かしたい場合、Seed設定で以下のようにローカルホストを指定します。非常にシンプルですね。
デフォルトの設定では、このようにローカルホストだけをノードとして追加しています。
簡単ですが、以上で必要な設定はすべて終了です。
storage-conf.xmlの全体像はどうなっているか
では、storage-conf.xmlがどのようになっているか見てみましょう。今回は分量の都合で割愛した部分もありますので、その部分は省略しました。
ここまでで、Cassandraの基本的な設定について説明しました。いますぐにすべてを覚えなくても大丈夫です。今後コードを書いていく中で徐々に覚えていくことができるでしょう。
開発環境を構築しよう
本連載では、開発環境としてEclipseを想定しています。まず開発環境を構築してみましょう。
以下のような手順でEclipse上にJavaプロジェクトを作成しておきます。
- ①Eclipseを起動してJavaプロジェクトを作成します。
プロジェクト名は「cassandra-examples」とします(名前はなんでも結構です)。
- ②前回動かしたCassandraのlibディレクトリ(%CASSANDRA_HOME%\lib)からjarをすべてコピーして、cassandra-examples/libに置きます。
- ③コピーしてきたjarすべてにクラスパスを通しておきます。
Cassandraへアクセスするための基本を知ろう
では、このプロジェクトでサンプルコードを書いてみましょう。CassandraへはThriftでのRPCを介して接続する必要があります。まずは接続のためのインスタンスであるTSocketとTProtocolの実装クラスを生成します。
ソケットを事前に開けておく必要があるので、CassandraにRPCする前にTSocket.open()を呼び出しておいてください。
最後に、CassandraにアクセスするクライアントコードであるCassandra.Clientインスタンスを生成します。その際にTProtocolインスタンスを渡す必要があるので注意してください。
以下は、localhostで9160番ポートで起動しているCassandraに接続しにいく実装コードです。
これで呼び出し部分は完成です。
次は終了部分です。Thriftのために使ったソケットはフラッシュして中身をクリアした後、クローズします。
動かしてみよう
というわけで、Thrift RPCの接続と切断を行うサンプルコードを書いて動かしてみましょう。コードを実行する前に、ローカルホストでCassandraを動かしておいてください。
次回はデータ挿入のサンプルを中心にご紹介しますが、その前に、今回のThriftを使ったRPCの基本を見せるサンプルとして、1件のカラムへデータを挿入する簡単なコードを紹介しておきます。
これをEclipse上から実行してみてください。「1件インサート完了」と出れば、成功です。もし出ない場合、もう一度設定とサンプルコードを見直してみてください。
インサート処理の中身については心配しないでください。次回詳しく説明します。
データが投入されたかどうか確認してみよう
本当に投入されたかどうかは、Cassandraのコマンドラインツールであるcassandra-cli.batで確認できます。
以下はコマンドラインからの実行の結果です。1件データが投入されているのがおわかりいただけたでしょうか。
これで開発環境の構築と、最も単純なクライアントコードが動くところまで来ました。ここまでで、Eclipse上のプロジェクトは次の図1のようになっているはずです。
今回は以下の2つのこと説明しました。
- Cassandraの基本的な設定方法
- Thriftを使ってCassandraへアクセスするための基本
次回はデータ投入を詳しく説明したあと、コマンドラインではなくコードから検索をかけてみます。お楽しみに。