2011年12月30日金曜日

LiftでCassandraを使ってみる

LiftでCassandraを使ってみる


NoSQLのDBであるCassandraをScalaで試した時のメモ。


Cassandraのダウンロード


$> wget http://ftp.jaist.ac.jp/pub/apache//cassandra/1.0.6/apache-cassandra-1.0.6-bin.tar.gz


解凍


$> tar zxvf apache-cassandra-1.0.6-bin.tar.gz


サーバの起動
cassandraの設定はconf/cassandra.yamlで設定されていて、
デフォルトでは、単一モードで起動するようになっているようだ。
なので、今回は何も変更を加えずにそのまま起動。

$> cd apache-cassandra-1.0.6 
$> ./bin/cassandra -f 


管理者権限で実行する必要があるかも。


CLIの起動
CLIはcassandraをコマンドラインで操作する為のクライアント。


CLIのインタプリタに入る。
$> ./bin/cassandra-cli -h localhost 


キースペースを表示する。
[default@unknown] show keyspaces; 

行末にセミコロンを付けるのを忘れずに。


Cassandraのデータ構造
クラスター:Cassandraのインスタンス
キースペース:データベースのようなもの
カラムファミリー:テーブルのようなもの


キースペースは、たいていは1つのアプリに1つ定義されるものらしい。
Scalaから操作するとき用に、あらかじめキースペースを定義しといたほうがよい感じ。


Liftのダウンロード
Liftは、Scalaで書かれたウェブフレームワーク。
Liftには、Scalaのビルドツールのsbtが付いているので、
ウェブアプリを作らないという時でも、ビルドするのに便利。

$> wget https://github.com/lift/lift_24_sbt/tarball/master -O lift2.4.tar.gz


解凍
$> tar zxvf lift2.4.tar.gz

jettyの起動
今回は、関係ないけど、とりあえず、jettyを起動。

$> cd lift-lift_24_sbt-05be36f/scala_29/lift_basic/
$> ./sbt
$> update
$> jetty-run

ブラウザでhttp://localhost:8080が表示されてればOK。

Hectorの取得


mavenのように、project/build/LiftProject.scalaに以下の記述を追加する。
"me.prettyprint" % "hector-core" % "0.8.0-2"

sbtのupdateコマンドでhectorをとってくる。
$> ./sbt
$> update


HectorでColumnの作成と取得
src/main/scala/TestCassandra.scalaを作成して以下のように編集する。
以下のコードは、ほとんどCassandra本家のサイトのサンプルのコピー。

import me.prettyprint._
import cassandra._
import service._
import hector.api._
import factory._
import ddl._
import template._
import serializers._


import java.util._


object TestCassandra {


  def main( args:Array[String] ) {


    val clusterName = "Test Cluster" // クラスターの名前
    val replicationFactor = 1 // リプリケーションするノードの数
    val keyspaceName = "test_keyspace" // キースペースの名前
    val cfName = "test_cf3" // カラムファミリの名前


    // クラスターの取得。名前はcassandraのクラスター名と同じじゃなくてよい。
    val cluster = HFactory.getOrCreateCluster(clusterName, "localhost:9160")


    // カラムファミリの定義
    val cfDef = HFactory.createColumnFamilyDefinition(keyspaceName, cfName, ComparatorType.BYTESTYPE)


    // カラムファミリの追加。既にあれば、例外を投げる
    try {
      cluster.addColumnFamily(cfDef, true )
    } catch {
      // 例外処理
    }


    // キースペースの定義
    val keyspaceDef = HFactory.createKeyspaceDefinition(keyspaceName, ThriftKsDef.DEF_STRATEGY_CLASS, replicationFactor, Arrays.asList(cfDef))


    // キースペースの追加
    if( keyspaceDef == null ) cluster.addKeyspace( keyspaceDef, true )
    
    // キースペースインスタンスの取得
    val ksp = HFactory.createKeyspace(keyspaceName, cluster)


    // カラムの更新
    val template = new ThriftColumnFamilyTemplate[String, String](ksp, cfName, StringSerializer.get(), StringSerializer.get());
    val updater = template.createUpdater("a key");
    updater.setString("domain", "www.datastax.com");
    updater.setLong("time", System.currentTimeMillis());


    template.update(updater);


    // カラムの取得
    val res = template.queryColumns("a key");
    val value = res.getString("domain");


  }


}

実行
sbtのrunコマンドでコンパイルと実行をする。

$>./sbt
$> run

カラムの更新と取得ができてればOK。