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

第4回 JavaでCassandraにアクセスする

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

動かしてみよう

というわけで,Thrift RPCの接続と切断を行うサンプルコードを書いて動かしてみましょう。コードを実行する前に,ローカルホストでCassandraを動かしておいてください。

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...

次回はデータ挿入のサンプルを中心にご紹介しますが,その前に,今回のThriftを使ったRPCの基本を見せるサンプルとして,1件のカラムへデータを挿入する簡単なコードを紹介しておきます。

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件インサート完了」と出れば,成功です。もし出ない場合,もう一度設定とサンプルコードを見直してみてください。

インサート処理の中身については心配しないでください。次回詳しく説明します。

データが投入されたかどうか確認してみよう

本当に投入されたかどうかは,Cassandraのコマンドラインツールであるcassandra-cli.batで確認できます。

以下はコマンドラインからの実行の結果です。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.

これで開発環境の構築と,最も単純なクライアントコードが動くところまで来ました。ここまでで,Eclipse上のプロジェクトは次の図1のようになっているはずです。

図1 Cassandraクライアントコードのプロジェクト

図1 Cassandraクライアントコードのプロジェクト

今回は以下の2つのこと説明しました。

  • Cassandraの基本的な設定方法
  • Thriftを使ってCassandraへアクセスするための基本

次回はデータ投入を詳しく説明したあと,コマンドラインではなくコードから検索をかけてみます。お楽しみに。

[コラム]Cassandraを複数ノードで動かすには

Cassandraを複数ノードで動かしたい場合,前述したノードの追加に加えて,いくつかやるべきことがあります。まず,Seedを複数登録します。以下の例では,host1から4までを登録しています。それに加えて,ThriftのRPCでコミュニケーションするための以下の設定を行う必要があります。

  • ① 各ノード間がコミュニケーションするためのホスト名とポート
  • ② クライアントからの接続を許可するホスト名とポート

①に関しては,ListenAddress/StoragePortで設定します。②に関しては,ThriftAddress/ThriftPortで設定します。どちらも,デフォルトではローカルホストを見るようになっています。そのため,複数ノード間での連携をしたい場合は以下のいずれかの処置が必要になります。

  • ホスト名を明示的に指定する
  • ブランクにしておいてOSのホスト設定に任せる

下記では,ノード4つでクラスタを組んで,ノード間のコミュニケーションは7000番ポートで行い,クライアントからのRPC要求は9160番で受けるように設定しています。

  <Seeds>
      <Seed>host1</Seed>
      <Seed>host2</Seed>
      <Seed>host3</Seed>
      <Seed>host4</Seed>
  </Seeds>

  <!-- ノード同士が通信するためのポート。 -->
  <ListenAddress></ListenAddress>
  <StoragePort>7000</StoragePort>

  <ThriftAddress>localhost</ThriftAddress>
  <ThriftPort>9160</ThriftPort>

このように,並べるだけで動きます。なお,複数ノードで動かす場合は,すべてのノードが同様の設定を持つ必要があります。

著者プロフィール

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

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

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

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