前回はCassandraのデータモデルについて説明しました。今回は実際にデータ設定とJavaコードからCassandraにアクセスする基本を見ていきます。コードはEclipseで書くことを前提に進めていきます。
Cassandraの設定で最低限必要な3つの項目
Cassandraの設定はすべてconf/
設定が必要なのは以下の項目になります。
- ① キースペース、
カラムファミリの設定 - ColumnType属性
- CompareWith属性
- CompareSubcolumnsWith属性
- ② コミットログとデータディレクトリを設定する
- ③ ノードを設定する
キースペース、カラムファミリを設定する
何はともあれ、
<Keyspaces>
<!-- キースペースは複数定義できる -->
<!-- キースペースKeyspace1の定義 -->
<Keyspace Name="Keyspace1">
<!-- カラムファミリStandard1の定義 -->
<ColumnFamily Name="Standard1" CompareWith="BytesType"/>
<!-- カラムファミリSuper1の定義 -->
<ColumnFamily Name="Super1" ColumnType="Super"
CompareWith="BytesType" CompareSubcolumnsWith="BytesType" />
Name属性は見たとおりなので割愛します。ColumnFamilyには、
ColumnFamilyで設定すべき属性は、
ColumnType属性
前回説明したとおり、
上記の例では、
- "Standard1"という名前のColumnFamily
→カラムだけが含まれるカラムファミリ - "Super1"という名前のColumnFamily
→ColumnTypeに"Super"と指定があるので、スーパーカラムだけが含まれるカラムファミリ
ColumnType属性はStandardまたはSuperのどちらかを選択できます。ColumnType属性に何も記載がないとStandardになります。
ColumnType設定項目 | 説明 |
---|---|
Standard | カラムファミリ内にカラムが含まれる |
Super | カラムファミリ内にスーパーカラムが含まれる |
CompareWith属性
次に目につく設定がCompareWithです。これは検索時のカラムのソートのための設定項目です。検索実行時にこのCompareWithで指定されたクラスを使ってカラムがソートされ、
CompareWith設定には、
CompareWith設定項目 | 説明 |
---|---|
BytesType | byte[]で比較する。値の検証はしない。 |
UTF8Type | UTF8でも文字列比較をする。 |
AsciiType | byte[]での比較に加えてUS-ASCIIでのエンコードの検証をする。 |
LongType | 64ビット長のlong値で比較する。 |
LexicalUUIDType | 128ビット長UUIDのbyte[]値を比較する。 |
TimeUUIDType | 128ビット長UUIDのタイムスタンプを比較する。 |
具体例を見てみましょう。以下の例ではUTF-8でカラムをソートします。
<ColumnFamily Name="utf8Order" CompareWith="UTF8Type" />
イメージとしては以下のようになります。カラム名がUTF-8順にソートされます。
SuperColumn:utf8Order | |||
---|---|---|---|
key | Column | ||
hoge | name | value | timestamp |
111 | 222 | 1273285360339 | |
aaa | value | 1273285360339 | |
name | shinpei | 1273285360339 | |
こんにちは | さようなら | 1273285360339 |
CompareSubcolumnsWith属性
CompareSubcolumnsWith属性は、
スーパーカラムの場合、
- スーパーカラムのソート
→CompareWith - スーパーカラム内のカラムのソート
→CompareSubcolumnsWith
という形で使い分けます。指定できる項目はCompareWithと同様です。
具体例を見てみましょう。
<ColumnFamily Name="time_utf8Order"
ColumnType="Super" CompareWith="LongType"
CompareSubcolumnsWith="UTF8Type"/>
この例ではCompareWithに"LongType"、
以下のようなイメージになります。
ColumnFamily:time_ |
||||
---|---|---|---|---|
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は、
- インデックス
- ブルームフィルタ
- データファイル
インデックスとブルームフィルタは読み込みを高速化するための仕組みです
このような内部構造をもっているため、
コミットログはCommitLogDirectoryで設定します。一方、
設定例としては以下のようになります。
<CommitLogDirectory>C:\cassandra\commitlog</CommitLogDirectory>
<DataFileDirectories>
<DataFileDirectory>C:\cassandra\data</DataFileDirectory>
</DataFileDirectories>
ノードを設定する
最後はノードの設定です。
Cassandraはマスターノードを持たないアーキテクチャのため、
単一ノードで動かしたい場合、
<Seeds>
<Seed>127.0.0.1</Seed>
</Seeds>
デフォルトの設定では、
簡単ですが、
storage-conf.xmlの全体像はどうなっているか
では、
<Storage>
<ClusterName>Test Cluster</ClusterName>
...
<!-- キースペースの指定 -->
<Keyspaces>
<Keyspace Name="Keyspace1">
<!-- カラムファミリの指定 -->
<ColumnFamily Name="Standard1" CompareWith="BytesType"/>
<ColumnFamily Name="Super1" ColumnType="Super" CompareWith="BytesType" CompareSubcolumnsWith="BytesType" />
<ColumnFamily Name="utf8Order" CompareWith="UTF8Type" />
<ColumnFamily Name="time_utf8Order" ColumnType="Super" CompareWith="LongType" CompareSubcolumnsWith="UTF8Type"/>
...
</Keyspace>
</Keyspaces>
...
<!-- コミットログとデータディレクトリ指定 -->
<CommitLogDirectory>C:\cassandra\cassandra-0.6.1\var\commitlog</CommitLogDirectory>
<DataFileDirectories>
<DataFileDirectory>C:\cassandra\cassandra-0.6.1\var\data</DataFileDirectory>
</DataFileDirectories>
<!-- ノード設定。開発用なので1ノード。 -->
<Seeds>
<Seed>127.0.0.1</Seed>
</Seeds>
...
</Storage>
ここまでで、
開発環境を構築しよう
本連載では、
以下のような手順でEclipse上にJavaプロジェクトを作成しておきます。
- ①Eclipseを起動してJavaプロジェクトを作成します。
プロジェクト名は「cassandra-examples」 とします (名前はなんでも結構です)。 - ②前回動かしたCassandraのlibディレクトリ
(%CASSANDRA_ HOME%\lib) からjarをすべてコピーして、 cassandra-examples/ libに置きます。 - ③コピーしてきたjarすべてにクラスパスを通しておきます。
Cassandraへアクセスするための基本を知ろう
では、
ソケットを事前に開けておく必要があるので、
最後に、
以下は、
TSocket transport = new TSocket("localhost", 9160);
TProtocol protocol = new TBinaryProtocol(transport);
try {
transport.open();
} catch (TTransportException e) {
//適宜、適切な例外を投げるなどしてください。
}
Cassandra.Client client = new Cassandra.Client(protocol);
これで呼び出し部分は完成です。
次は終了部分です。Thriftのために使ったソケットはフラッシュして中身をクリアした後、
try {
transport.flush();
} catch (TTransportException e) {
//適宜、適切な例外を投げるなどしてください。
} finally {
transport.close();
}
動かしてみよう
というわけで、
C:\cassandra\apache-cassandra-0.6.1>bin\cassandra.bat Starting Cassandra Server Listening for transport dt_socket at address: 8888 INFO 23:21:29,072 Auto DiskAccessMode determined to be mmap INFO 23:21:29,961 Saved Token not found. Using 133651919147845386411055611530227208445 INFO 23:21:29,963 Saved ClusterName not found. Using Test Cluster INFO 23:21:30,010 Creating new commitlog segment C:\cassandra\commitlog\CommitLog-1273501290010.log INFO 23:21:30,096 Starting up server gossip INFO 23:21:30,272 Binding thrift service to localhost/127.0.0.1:9160 INFO 23:21:30,285 Cassandra starting up...
次回はデータ挿入のサンプルを中心にご紹介しますが、
package examples;
import org.apache.cassandra.thrift.Cassandra;
import org.apache.cassandra.thrift.ColumnPath;
import org.apache.cassandra.thrift.ConsistencyLevel;
import org.apache.cassandra.thrift.InvalidRequestException;
import org.apache.cassandra.thrift.TimedOutException;
import org.apache.cassandra.thrift.UnavailableException;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSocket;
import org.apache.thrift.transport.TTransportException;
/**
* シンプルなインサート。
*
*/
public class SimpleInsert {
public static final String KEYSPACE = "Keyspace1";
public static final String COLUMN_FAMILY = "Standard1";
public static void main(String[] args) {
TSocket transport = new TSocket("localhost", 9160);
TProtocol protocol = new TBinaryProtocol(transport);
try {
transport.open();
} catch (TTransportException e) {
throw new RuntimeException(e);
}
Cassandra.Client client = new Cassandra.Client(protocol);
try {
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);
} catch (InvalidRequestException e) {
throw new RuntimeException(e);
} catch (UnavailableException e) {
throw new RuntimeException(e);
} catch (TimedOutException e) {
throw new RuntimeException(e);
} catch (TException e) {
throw new RuntimeException(e);
} finally {
try {
transport.flush();
} catch (TTransportException e) {
throw new RuntimeException(e);
} finally {
transport.close();
}
}
System.out.println("1件インサート完了.");
}
}
これをEclipse上から実行してみてください。
インサート処理の中身については心配しないでください。次回詳しく説明します。
データが投入されたかどうか確認してみよう
本当に投入されたかどうかは、
以下はコマンドラインからの実行の結果です。1件データが投入されているのがおわかりいただけたでしょうか。
C:\cassandra\apache-cassandra-0.6.1>bin\cassandra-cli.bat Starting Cassandra Client Welcome to cassandra CLI. cassandra> connect localhost/9160 Connected to: "Test Cluster" on localhost/9160 cassandra> get Keyspace1.Standard1['sample1'] => (column=686f6765, value=sample_value, timestamp=1273501448025) Returned 1 results.
これで開発環境の構築と、

今回は以下の2つのこと説明しました。
- Cassandraの基本的な設定方法
- Thriftを使ってCassandraへアクセスするための基本
次回はデータ投入を詳しく説明したあと、