Cassandraのはじめ方─手を動かしてNoSQLを体感しよう

第5回 APIの全体像とデータの投入

この記事を読むのに必要な時間:およそ 5.5 分

ColumnPathでデータの格納場所を,ConsistencyLevelで一貫性レベルを指定

前回の最後にご紹介したコードの抜粋を使っておさらいしておくと,実際には以下のような形で使います。

	final String key = "sample1";
	final String columnName = "hoge";
	final String value = "sample_value";
	final long timestamp = System.currentTimeMillis();

	// ColumnPathは単一のカラムの位置を特定するためのクラス(後述)
	final ColumnPath columnPath = new ColumnPath(COLUMN_FAMILY);
	columnPath.setColumn(columnName.getBytes());

	// 1件カラムをインサート
	client.insert(KEYSPACE, key, columnPath, value.getBytes(),
			timestamp, ConsistencyLevel.ONE);

この中で,ColumnPathとConsistencyLevelの2つはまだあまり馴染みの無いと思います。くわしく見ていきましょう。

ColumnPath

ColumnPathはカラムファミリとカラム名を特定するためのクラスで,その名のとおりデータをどこに格納すればよいかを明示します。ディレクトリ構造におけるパスのような扱いと思ってもらえれば差し支えありません。そのため以下の指定を行う必要があります。

表4 ColumnPathで指定する項目

カラムファミリ名
カラム名
スーパーカラム名(スーパーカラムを使っている場合)

図1 ColumnPath

図1 ColumnPath

ConsistencyLevel

Cassandraでは全ての操作で,その操作に対する一貫性レベルをクライアントコードから与える形式をとっています。全ての操作の引数にConsistencyLevelのenumがついてくるのはそのためです。ConsistencyLevelは書き込み時と読み込み時で表5のような意味を持っています。

表5 ConsistencyLevelの一覧

ConsistencyLevel読み込み時書き込み時
ZERO使用不可何も保障しない書き込み。非同期に実行される
ONEもっとも最初に読めた1ノードのデータを返す(※7)クライアントに返すまでの間に1ノードに書き込まれることを保障する
QUORUM全ノードの内,レプリケーション数 / 2+1からデータが読めたら返す。返すデータは最新のタイムスタンプのものを返すクライアントに返すまでの間に(レプリケーション数 / 2+1)のノードに書き込まれることを保障する
DCQUORUM0.6.1ではALLと同等(※8)0.6.1ではALLと同等
DCQUORUMSYNC0.6.1ではALLと同等0.6.1ではALLと同等
ALL全ノードから読めた場合,データを返す(※9)クライアントに返すまでの間にレプリケーション数だけ書き込まれる事を保障する
ANY使用不可1度どこかのタイミングで書き込まれる事を保障する
※7
その後バックグラウンドスレッドで一貫性チェックを行い,一貫性が取れていない場合はデータを修復します。これをread repairといいます。
※8
本来は (レプリケーション数 - 1) / 2 のデータがデータセンター間でQUORUMの一貫性を維持しデータを返します。
※9
現状だとget_count,get_range_slicesでしか使えないようです。

注意すべき点は,これらの一貫性はノード数全体ではなく,storage-conf.xmlで指定したレプリケーション数によって決まる点です。具体的には<ReplicationFactor>の設定で,キースペースごとに指定します。

RDBMSのようなACIDでの強度な一貫性と異なり,CassandraはEventual Consistency(一貫性のある状態にいつか到達する)という思想に基づき設計されています。つまり,一貫性を緩める代わりに応答速度を向上させるという狙いがあります。ConsistencyLevelにバリエーションがあるのもそのためです。

スーパーカラム内の1つのカラムにデータを入れる

ではサンプルコードに戻って,スーパーカラム内の1つのカラムにデータを入れてみましょう。

スーパーカラム内のカラムにデータを入れる方法は,カラムのときとほとんど変わりません。違うのはColumnPathでどのスーパーカラムのどのカラムかを指定するようにしている点だけです。スーパーカラムとカラムは,以下のようにして指定します。

  • columnPath.setSuper_column() → スーパーカラム名を指定
  • columnPath.setColumn() → カラム名を指定

リスト1 SimpleSuperColumnInsert.java

final String key = "super_sample1";
final String superColumnName = "sample1";
final String columnName = "foo";
final String value = "super_sample_value";
final long timestamp = System.currentTimeMillis();

// ColumnPathは単一のカラムの位置を特定するためのクラス
final ColumnPath columnPath = new ColumnPath(COLUMN_FAMILY);
// スーパーカラム名を指定
columnPath.setSuper_column(superColumnName.getBytes());
// カラム名を指定
columnPath.setColumn(columnName.getBytes());

// 1件カラムをインサート
client.insert(KEYSPACE, key, columnPath, value.getBytes(),
		timestamp, ConsistencyLevel.ONE);

著者プロフィール

大谷晋平(おおたにしんぺい)

オープンソースプログラマ。WebフレームワークT2の開発をしながらHadoop/NoSQLミドルウェアにも手を出す。最近ではもっぱらHadoop,Cassandra,Avro,kumofsなどに興味津々。

blog:http://d.hatena.ne.jp/shot6/

Twitter:http://twitter.com/shot6/