読者です 読者をやめる 読者になる 読者になる

分散 KVS の Voldemort を Groovy で使ってみる

Java Groovy KVS NoSQL

Java で書かれた分散 KVS の Voldemort を簡単なサンプルを作って試してみた。

使用した環境は以下の通り。

  • Groovy 1.7.0
  • Voldemort 0.60.1

サーバーの作成と実行

今のところ、Voldemort の bin ディレクトリには .sh ファイルしか用意されていないため、Windows 環境で実行するには自分で起動ファイルを用意する必要がある。

ただ、必要最小限のサーバーを実行するだけなら、以下のように VoldemortConfig と VoldemortServer クラスを使って簡単に書けるので大した問題ではない。

test_server.groovy
import voldemort.server.*

def config = VoldemortConfig.loadFromVoldemortHome(args[0])
def server = new VoldemortServer(config)

//サーバー起動
server.start()

次に、Voldemort サーバーを実行するには cluster.xml, server.properties, stores.xml ファイルを config ディレクトリ内に用意する必要がある。

今回は Voldemort に用意されている config/single_node_cluster/config ディレクトリをカレントディレクトリにコピーして、以下のような変更を行って使用する事にした。

  • server.properties ファイルの編集
    • bdb.cache.size を JVM の使用メモリに合わせて調整
    • bdb.write.transactions を true に変更(これを true にしないと永続化されない)
  • stores.xml の view 要素を削除(実行時にここで使用されているクラスがロードできないとのエラーが出たため削除する事にした)
config/server.properties 例
・・・
http.enable=true
socket.enable=true

# BDB
bdb.write.transactions=true
bdb.flush.transactions=false
bdb.cache.size=100M
・・・

サーバーの実行は CLASSPATH に Voldemort の dist/voldemort-0.60.1.jar と lib ディレクトリ内の JAR ファイルが設定されるようにして、以下のように先程のスクリプトを実行するだけでよい。(カレントディレクトリに config ディレクトリを用意している事が前提)

サーバー実行例
>groovy test_server.groovy .

ちなみに、カレントディレクトリの構成は以下のようにした。

  • test_server.groovy ファイル
  • config ディレクトリ
    • cluster.xml ファイル
    • server.properties ファイル
    • stores.xml ファイル

クライアントの作成と実行

クライアントは以下の通り。
接続先のポート番号は config/cluster.xml ファイルの socket-port の番号、getStoreClient に渡す名称は config/stores.xml の stores/store/name の値を使う点に注意。

test_client.groovy
import voldemort.client.*
import voldemort.versioning.Versioned

def factory = new SocketStoreClientFactory(new ClientConfig().setBootstrapUrls("tcp://localhost:6666"))
def client = factory.getStoreClient("test")

def k = "a1"
def v = client.get(k)

if (v == null) {
    //未登録なら値を登録
    client.put(k, new Versioned("テストデータ"))
}
else {
    v.setObject(v.value + "_next")
    //値に _next を付けて更新
    client.put(k, v)
}

println "registered : ${client.get(k)}"

このスクリプトを実行すると以下のようになる。
なお、サーバーと同様に CLASSPATH へ Voldemort の dist/voldemort-0.60.1.jar と lib ディレクトリ内の JAR ファイルが設定されるようにしてから実行すればよい。

クライアント実行例(サーバーが起動している事が前提)
>groovy test_client.groovy
registered : [テストデータ, version(0:1)]
>groovy test_client.groovy
registered : [テストデータ_next, version(0:2)]

以上のように Voldemort は比較的簡単に試してみる事ができる。

Gant を使った実行スクリプト

最後に、Voldemort の bin/voldemort-server.sh や bin/voldemort-shell.sh と同様の処理を Gant(Ant の Groovy 版)スクリプトで実現してみた。

bin/voldemort-server.sh の場合は以下のようになる。(環境変数 VOLDEMORT_HOME に voldemort のホームディレクトリのパスを設定しておくことが前提)

voldemort-server.gant
ant.property(environment: "env")
voldemortHome = ant.antProject.properties."env.VOLDEMORT_HOME"

target(default: "") {
    java(classname: "voldemort.server.VoldemortServer", fork: true) {
        jvmarg(line: "-Xmx2G -server -Dcom.sun.management.jmxremote")
        classpath {
            fileset(dir: "${voldemortHome}/dist", includes: "*.jar")
            fileset(dir: "${voldemortHome}/lib", includes: "*.jar")
            fileset(dir: "${voldemortHome}/contrib/hadoop-store-builder/lib", includes: "*.jar")
            pathelement(path: "${voldemortHome}/dist/resources")
        }
        arg(value: "${config}")
    }
}

実行例は以下。

実行例
>gant -f voldemort-server.gant -D config=.
default:
     [java] metadata init().
     [java] admin-port not defined for node:0 using default value:6667 as (socket_port + 1):
     [java] Using BIO Connector.
     [java] Starting voldemort-server
     [java] Starting 7 services.
     [java] Starting storage-service
     [java] Initializing bdb storage engine.
     [java] Initializing read-only storage engine.
     [java] Creating shared BDB environment:
     [java]     BDB cache size = 268435456
     [java]     BDB je.cleaner.threads = 1
     [java]     BDB je.cleaner.minUtilization = 50
     [java]     BDB je.cleaner.minFileUtilization = 5
     [java]     BDB je.log.fileMax = 62914560
     [java] Initializing stores:
     [java] Opening store 'test' (bdb).
     [java] All stores initialized.
     [java] Starting scheduler-service
     [java] Starting async-scheduler
     [java] Starting asyncOperationRunner
     [java] Starting http-service
     [java] Logging to org.slf4j.impl.Log4jLoggerAdapter(org.mortbay.log) via org.mortbay.log.Slf4jLog
     [java] jetty-6.1.18
     [java] Started SelectChannelConnector@0.0.0.0:8081
     [java] HTTP service started on port 8081
     [java] Starting socket-service
     [java] Starting voldemort socket server (socket-server) on port 6666
     [java] Starting socket-service
     [java] Starting voldemort socket server (admin-server) on port 6667
     [java] Starting jmx-service
     [java] Overwriting mbean voldemort.server.socket:type=SocketService
     [java] Startup completed in 1051 ms.

次に、bin/voldemort-shell.sh は以下のようになる。

voldemort-shell.gant
ant.property(environment: "env")
voldemortHome = ant.antProject.properties."env.VOLDEMORT_HOME"

target(default: "") {
    java(classname: "jline.ConsoleRunner") {
        classpath {
            fileset(dir: "${voldemortHome}/dist", includes: "*.jar")
            fileset(dir: "${voldemortHome}/lib", includes: "*.jar")
            fileset(dir: "${voldemortHome}/contrib/hadoop-store-builder/lib", includes: "*.jar")
            pathelement(path: "${voldemortHome}/dist/resources")
        }
        arg(line: "voldemort.VoldemortClientShell ${store} ${url}")
    }
}

実行例は以下。実行後にプロンプトが出て、コマンド入力を受け付けるようになる。(なぜか exit を実行すると例外が発生するようなので注意)

実行例(help コマンドと get コマンドを使っている)
>gant -f voldemort-shell.gant -D store=test -D url=tcp://localhost:6666
default:
Established connection to test via tcp://localhost:6666
> help
Commands:
put key value -- Associate the given value with the key.
get key -- Retrieve the value associated with the key.
getall key -- Retrieve the value(s) associated with the key.
delete key -- Remove all values associated with the key.
preflist key -- Get node preference list for given key.
help -- Print this message.
exit -- Exit from this shell.

> get "a1"
version(0:2): "テストデータ_next"