Symfoware

Symfowareについての考察blog

Voldemortのデータにオブジェクトを登録する方法(java-serialization使用)

DebianにVoldemortをインストール
Windows + Javaからの接続を試しました。
Debianにkey-value storage systemの「Voldemort」をインストールする
Debianで動作しているVoldemortをWindows + Javaで操作する


「keyやvalueにはシリアライズした色々なデータを登録できるよ」と
記載されているのですが、どうやって使用すればよいかわからずはまったので、
メモしておきます。



java-serialization



Java標準のserializeを使用して、シリアライズしたデータの登録が
出来るようなので試してみます。


この機能を使用するためには、stores.xmlを編集する必要があります。

%Voldemort%/config/single_node_cluster/config/stores.xml
このファイルを開きます。

デフォルトではこんな感じだと思います。


<stores>
    <store>
        <name>test</name>
        <persistence>bdb</persistence>
        <routing>client</routing>
        <replication-factor>1</replication-factor>
        <required-reads>1</required-reads>
        <required-writes>1</required-writes>
        <key-serializer>
            <type>string</type>
        </key-serializer>
        <value-serializer>
            <type>string</type>
        </value-serializer>
    </store>
</stores>




value-serializerのtypeで、データを保存するときの形式を指定します。
Javaのシリアライズが使いたいので、以下のように編集します。


<stores>
    <store>
        <name>test</name>
        <persistence>bdb</persistence>
        <routing>client</routing>
        <replication-factor>1</replication-factor>
        <required-reads>1</required-reads>
        <required-writes>1</required-writes>
        <key-serializer>
            <type>string</type>
        </key-serializer>
        <value-serializer>
            <!-- java-serializationに変更 -->
            <type>java-serialization</type>
        </value-serializer>
    </store>
</stores>




設定ファイルを変更したら、Voldemortを再起動します。




登録するデータオブジェクト



登録するオブジェクトを作成しました。
titleとdetailsという二つのフィールドを持つオブジェクトです。
※テストなので、適当です。


■Data.java


package com.fc2.blog68.symfoware.voldemort;

import java.io.Serializable;

public class Data implements Serializable {

    private static final long serialVersionUID = 2496199384883564160L;
    
    public String title;
    public String details;

}




※ちなみに、ちゃんとimplements Serializableしていないと、
登録実行時にこんなエラーが表示されます。


Exception in thread "main" voldemort.serialization.SerializationException: java.io.NotSerializableException: com.fc2.blog68.symfoware.voldemort.Data
    at voldemort.serialization.ObjectSerializer.toBytes(ObjectSerializer.java:47)
    at voldemort.store.serialized.SerializingStore.put(SerializingStore.java:109)
    at voldemort.store.DelegatingStore.put(DelegatingStore.java:68)
    at voldemort.client.DefaultStoreClient.put(DefaultStoreClient.java:208)
    at voldemort.client.DefaultStoreClient.put(DefaultStoreClient.java:193)
    at com.fc2.blog68.symfoware.voldemort.Sample.main(Sample.java:27)
Caused by: java.io.NotSerializableException: com.fc2.blog68.symfoware.voldemort.Data
    at java.io.ObjectOutputStream.writeObject0(Unknown Source)
    at java.io.ObjectOutputStream.writeObject(Unknown Source)
    at voldemort.serialization.ObjectSerializer.toBytes(ObjectSerializer.java:44)
    ... 5 more






このオブジェクトをVoldemortに登録するソースはこんな感じになります。


package com.fc2.blog68.symfoware.voldemort;

import voldemort.client.ClientConfig;
import voldemort.client.SocketStoreClientFactory;
import voldemort.client.StoreClient;
import voldemort.client.StoreClientFactory;

public class Sample {
    public static void main(String[] args) {
        
        String[] bootstrapUrls = new String[]{"tcp://192.168.1.150:6666"};
        
        ClientConfig cc = new ClientConfig();
        cc.setBootstrapUrls(bootstrapUrls);
        
        StoreClientFactory factory = new SocketStoreClientFactory(cc);
        
        //最初にキーの型、二番目に登録するデータの型を定義する
        StoreClient<String, Data> client = factory.getStoreClient("test");
        
        //登録用のオブジェクトを生成
        Data data = new Data();
        data.title = "日本語タイトル";
        data.details = "日本語の詳細を設定";
        
        //自作のオブジェクトを登録
        client.put("key", data);
        
        //登録したデータを取得し、表示
        data = client.getValue("key");
        System.out.println(data.title);
        System.out.println(data.details);

    }
}






ミソはStoreClientを生成するときで、


StoreClient<[keyのオブジェクト], [valueのオブジェクト]>



という形式で指定してやります。



StoreClient<String, Data>


と宣言することで、
keyにString
valueに作成したcom.fc2.blog68.symfoware.voldemort.Dataオブジェクト
がそれぞれ使用できるようになります。

また、シリアライズはVoldemortが勝手にやってくれるので
プログラム中で意識することはありません。



サンプルを実行してみると・・・

[2010-04-18 11:11:59,426 voldemort.client.DefaultStoreClient] INFO bootstrapping metadata.
日本語タイトル
日本語の詳細を設定





狙い通りの動きになりました。






テーマ:データベース - ジャンル:コンピュータ

  1. 2010/04/22(木) 12:13:59|
  2. Voldemort
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

Debianで動作しているVoldemortをWindows + Javaで操作する

DebianにVoldemortをインストールして、動作を確認しました。
Debianにkey-value storage systemの「Voldemort」をインストールする


今度は、別端末のWindows + Javaで接続し、データの操作を行ってみます。

これが苦難の道のりになろうとは・・・



サンプルプログラム



Voldemortのモジュールの中にサンプルプログラムがあります。
%Voldemort%/example/java/voldemort/examples/ClientExample.java
これを参考にサンプルプログラムを作成しました。

ソースはこんな感じです。

■Sample.java


package com.fc2.blog68.symfoware.voldemort;

import voldemort.client.ClientConfig;
import voldemort.client.SocketStoreClientFactory;
import voldemort.client.StoreClient;
import voldemort.client.StoreClientFactory;

public class Sample {
    public static void main(String[] args) {
        
        String[] bootstrapUrls = new String[]{"tcp://192.168.1.250:6666"};
        
        ClientConfig cc = new ClientConfig();
        cc.setBootstrapUrls(bootstrapUrls);
        
        StoreClientFactory factory = new SocketStoreClientFactory(cc);
        StoreClient<String, String> client = factory.getStoreClient("test");
        
        client.put("key", "日本語だぜ");
        
        System.out.println(client.getValue("key"));

    }
}






実行に必要な最低限のjarファイルは4つ。

以下の3つのjarは、%Voldemort%/libにあります。

google-collect-1.0.jar
jdom-1.1.jar
log4j-1.2.15.jar



以下のjarは、%Voldemort%/dist

voldemort-0.80.1.jar



これらをビルドパスに含めておきます。





エラーその1



実行してみると、こんなエラーが出るかと思います。


Exception in thread "main" java.lang.IllegalArgumentException: java.lang.ClassNotFoundException: voldemort.store.views.UpperCaseView
    at voldemort.utils.ReflectUtils.loadClass(ReflectUtils.java:59)
    at voldemort.xml.StoreDefinitionsMapper.loadTransformation(StoreDefinitionsMapper.java:250)
    at voldemort.xml.StoreDefinitionsMapper.readView(StoreDefinitionsMapper.java:229)
    at voldemort.xml.StoreDefinitionsMapper.readStoreList(StoreDefinitionsMapper.java:125)
    at voldemort.client.AbstractStoreClientFactory.getRawStore(AbstractStoreClientFactory.java:134)
    at voldemort.client.DefaultStoreClient.bootStrap(DefaultStoreClient.java:80)
    at voldemort.client.DefaultStoreClient.<init>(DefaultStoreClient.java:74)
    at voldemort.client.AbstractStoreClientFactory.getStoreClient(AbstractStoreClientFactory.java:124)
    at voldemort.client.AbstractStoreClientFactory.getStoreClient(AbstractStoreClientFactory.java:118)
    at com.fc2.blog68.symfoware.voldemort.Sample.main(Sample.java:16)
Caused by: java.lang.ClassNotFoundException: voldemort.store.views.UpperCaseView
    at java.net.URLClassLoader$1.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClassInternal(Unknown Source)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Unknown Source)
    at voldemort.utils.ReflectUtils.loadClass(ReflectUtils.java:57)
    ... 9 more




同じ内容で困っている人を見つけました。
http://code.google.com/p/project-voldemort/issues/detail?id=231


このエラーの解決方法は2つあります。

1つめの方法は、
voldemort.store.views.UpperCaseView
このクラスは、テスト用のjarファイルに含まれています。

そのため、
%Voldemort%/dist/voldemort-test-0.80.1.jar
このjarファイルをビルドパスに含めればエラーは発生しません。


2つめの方法ですが、このエラーが発生する根本的な原因は
Voldemortの起動時、

# bin/voldemort-server.sh config/single_node_cluster



このように、config/single_node_clusterの設定ファイルを指定して起動しています。




config/single_node_cluster/config/stores.xml



このファイルの中身を見てみると・・・


<stores>
    <store>
        <name>test</name>
        <persistence>bdb</persistence>
        <routing>client</routing>
        <replication-factor>1</replication-factor>
        <required-reads>1</required-reads>
        <required-writes>1</required-writes>
        <key-serializer>
            <type>string</type>
        </key-serializer>
        <value-serializer>
            <type>string</type>
        </value-serializer>
    </store>
    <view>
        <name>test-view</name>
        <view-of>test</view-of>
        <view-class>
            voldemort.store.views.UpperCaseView
        </view-class>
        <value-serializer>
            <type>string</type>
        </value-serializer>
    </view>
</stores>



まだ機能の詳細は調べていませんが、「view」という機能を使用する箇所で、
クラス名の指定を行っており、これが悪さをしているようです。

そこで、以下のように「view」のタグをごっそり削ってしまえば
エラーは発生しなくなります。


<stores>
    <store>
        <name>test</name>
        <persistence>bdb</persistence>
        <routing>client</routing>
        <replication-factor>1</replication-factor>
        <required-reads>1</required-reads>
        <required-writes>1</required-writes>
        <key-serializer>
            <type>string</type>
        </key-serializer>
        <value-serializer>
            <type>string</type>
        </value-serializer>
    </store>
</stores>







エラーその2



エラーその1の原因を取り去ると、今度はこんなエラーに遭遇しました。


Exception in thread "main" voldemort.store.InsufficientOperationalNodesException: 1 reads required, but 0 succeeded.
    at voldemort.store.routed.RoutedStore.get(RoutedStore.java:562)
    at voldemort.store.routed.RoutedStore.getVersions(RoutedStore.java:869)
    at voldemort.store.routed.RoutedStore.getVersions(RoutedStore.java:1)
    at voldemort.store.DelegatingStore.getVersions(DelegatingStore.java:85)
    at voldemort.store.serialized.SerializingStore.getVersions(SerializingStore.java:114)
    at voldemort.store.DelegatingStore.getVersions(DelegatingStore.java:85)
    at voldemort.client.DefaultStoreClient.getVersions(DefaultStoreClient.java:134)
    at voldemort.client.DefaultStoreClient.put(DefaultStoreClient.java:180)
    at com.fc2.blog68.symfoware.voldemort.Sample.main(Sample.java:18)
Caused by: voldemort.store.UnreachableStoreException: Failure while checking out socket for localhost:6666(vp1):
    at voldemort.store.socket.SocketPool.checkout(SocketPool.java:92)
    at voldemort.store.socket.SocketStore.getVersions(SocketStore.java:178)
    at voldemort.store.socket.SocketStore.getVersions(SocketStore.java:1)
    at voldemort.store.DelegatingStore.getVersions(DelegatingStore.java:85)
    at voldemort.store.routed.RoutedStore$2.execute(RoutedStore.java:86)
    at voldemort.store.routed.RoutedStore$GetCallable.call(RoutedStore.java:900)
    at voldemort.store.routed.RoutedStore$GetCallable.call(RoutedStore.java:1)
    at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)
    at java.util.concurrent.FutureTask.run(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Caused by: java.net.ConnectException: Connection refused: connect
    at java.net.PlainSocketImpl.socketConnect(Native Method)
    at java.net.PlainSocketImpl.doConnect(Unknown Source)
    at java.net.PlainSocketImpl.connectToAddress(Unknown Source)
    at java.net.PlainSocketImpl.connect(Unknown Source)
    at java.net.SocksSocketImpl.connect(Unknown Source)
    at java.net.Socket.connect(Unknown Source)
    at voldemort.store.socket.SocketResourceFactory.create(SocketResourceFactory.java:84)
    at voldemort.store.socket.SocketResourceFactory.create(SocketResourceFactory.java:1)
    at voldemort.utils.pool.KeyedResourcePool.attemptGrow(KeyedResourcePool.java:153)
    at voldemort.utils.pool.KeyedResourcePool.checkoutOrCreateResource(KeyedResourcePool.java:133)
    at voldemort.utils.pool.KeyedResourcePool.checkout(KeyedResourcePool.java:106)
    at voldemort.store.socket.SocketPool.checkout(SocketPool.java:87)
    ... 11 more





このエラーの原因は、クラスターの設定を行っているファイルにあります。


config/single_node_cluster/config/cluster.xml



上記のファイルを開くと、hostの指定が「localhost」になっているかと思います。


<cluster>
        <name>mycluster</name>
        <server>
                <id>0</id>
                <host>localhost</host>
                <http-port>8081</http-port>
                <socket-port>6666</socket-port>
                <partitions>0, 1</partitions>
        </server>
</cluster>




以下のように、localhostの部分をサーバーのIPアドレスに変更してやります。


<cluster>
        <name>mycluster</name>
        <server>
                <id>0</id>
                <host>192.168.1.250</host>
                <http-port>8081</http-port>
                <socket-port>6666</socket-port>
                <partitions>0, 1</partitions>
        </server>
</cluster>








エラーその3



実行には関係ないのですが、せっかくなのでlog4jのエラーもつぶしておきます。


log4j:WARN No appenders could be found for logger (voldemort.client.DefaultStoreClient).
log4j:WARN Please initialize the log4j system properly.



上記のようなlog4jのエラーが表示されているかと思います。

これを解消するには、
%Voldemort%/dist/resourcesにある「log4j.properties」をコピーし、
classファイルがある階層に保存してやります。

サンプルソースをビルドすると、こんな階層でclassファイルが生成されます。

%classes%/com/fc2/blog68/symfoware/voldemort/Sample.class




%classes%と同じ階層にlog4j.propertiesを保存してやります。


%classes%/log4j.properties



これで、log4jのエラーが表示されなくなると思います。




実行結果



Debian上のVoldemortを起動させておいて、サンプルプログラムを実行すると


[2010-04-18 19:07:10,305 voldemort.client.DefaultStoreClient] INFO bootstrapping metadata.
日本語だぜ



ちゃんとデータの登録と検索が行えました。


・・・長かった。



テーマ:データベース - ジャンル:コンピュータ

  1. 2010/04/21(水) 12:11:15|
  2. Voldemort
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

key-value storage system「Voldemort」の特徴

名前が気に入ったのでVoldemort(ヴォルデモート)というデータベースをDebianにインストールしてみました。
Debianにkey-value storage systemの「Voldemort」をインストールする


あまり詳細を知らずにインストールしてみたので、改めて
このデータベースの特徴を調べてみます。


Voldemort is a distributed key-value storage system



Voldemortのトップページ
http://project-voldemort.com/
ここに記載されている内容はこんな感じだと思います。
※あまり自信はありませんが。



Data is automatically replicated over multiple servers.

データは自動的に複数のサーバーに複製されます。





Data is automatically partitioned so each server contains only a subset of the total data

各サーバーのデータは、全データのサブセットのみが含まれるよう自動的に分割して配置されます。



複数のサーバーを競うさせた場合、自動的に同期がとられるもよう。
全てのサーバーがまったく同じデータを持つかというとそういうわけではなく、
分散して配置されるようです。

Googleのように、「世界のどこか3箇所にデータが保存されています」的なことかなと思います。




Server failure is handled transparently

サーバーの障害はわかりやすく処理されます



訳があやしいのですが、障害からの復旧が楽という意味でしょうか?




Pluggable serialization is supported to allow rich keys and values including lists
and tuples with named fields, as well as to integrate with common serialization frameworks
like Protocol Buffers, Thrift, and Java Serialization

シリアライズ用のプラグインは、さまざまななキー値と、リストや名前付きのタプルを含む値の保持を
サポートしています。
GoogleのProtocol BuffersやThrift、そしてJava標準のSerialization等、
一般的なシリアライズ用フレームワークが使用できます。



おそらく、専用の接続クライアントだけではなく、一般的なRPC serializeの
フレームワークが使えるよということだと思います。
Thriftも使えるようなので、使ってみようと思います。




Data items are versioned to maximize data integrity in failure scenarios
without compromising availability of the system

登録されたデータはバージョン管理され、障害発生時でも整合性を保ちます。



これも訳が怪しいのですが・・・
データはバージョン管理されていることは確認したので、障害発生時はバージョンが
最大のものを再配置するということかと思います。




Each node is independent of other nodes with no central point of failure or coordination

各ノードは独立しており、単一障害点にはなりません。



Cassandraしかり、最近の分散システムは、単一障害点をおかないような設計になっていますね。




Good single node performance:
you can expect 10-20k operations per second depending on the machines,
the network, the disk system, and the data replication factor

単一ノードのパフォーマンスが良い。
端末やネットワーク、ディスクシステム、そしてデータ複製の要因に応じて、
一秒間当たり10-20kのデータ操作が可能です。



これも訳があやしいのですが、単一ノードに対しコンスタントに10-20kのデータ操作が
可能であるということかなと思っています。




Support for pluggable data placement strategies to support things like
distribution across data centers that are geographically far apart.

データ配置に関する部分をプラグインとしてサポートしているので、
地理的に離れているデータセンター間のレプリケーションが行いやすい。



データ複製の仕組み自体がプラグインで提供されているので、
動作環境に応じて好きにカスタマイズできることが売りですよ。
というこだと解釈しました。



なかなかステキなデータベースのようです。
今度、Debian + Voldemortのサーバーに、Windows + Javaから接続し、
データの操作を行ってみたいと思います。






テーマ:プログラミング - ジャンル:コンピュータ

  1. 2010/04/20(火) 12:09:38|
  2. Voldemort
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集

Debianにkey-value storage systemの「Voldemort」をインストールする

データベースについて調べ物をしていると、「Voldemort」(ヴォルデモート)という
key-valueデータベースを見つけました。

Project Voldemort


Voldemortといえば、ハリー・ポッターに出てくる
「例のあの人」「名前を呼んではいけないあの人」
とか呼ばれている魔法使いの名前ですね。

名前が気に入ったので、Debianにインストールしてみます。




Javaのインストール



VoldemortはJavaで出来ていますので、Javaの実行環境を準備しておきます。
以前、DebianにJavaをインストールしたときのメモはこちら。
Debian lennyにJavaをインストールする





モジュールの取得と設定



Quickstart
ここに記載されている手順を参考にインストールしてみます。

今回は、/optにモジュールをダウンロードし、展開しました。



# cd /opt/
# wget http://github.com/downloads/voldemort/voldemort/voldemort-0.80.1.tar.gz
# tar zxf voldemort-0.80.1.tar.gz
# ln -s /opt/voldemort-0.80.1 /opt/voldemort




/opt/に移動。
wgetでモジュールを取得。
tar zxfで取得したモジュールを解凍。
という手順です。

最後に、/opt/voldemort-0.80.1に対して、/opt/voldemortというリンクを設定しています。





サーバーの起動とデータの登録



/opt/voldemortに移動して、サーバーを起動します。


# cd /opt/voldemort
# bin/voldemort-server.sh config/single_node_cluster > /tmp/voldemort.log &
[1] 18924



起動してくれた模様。


Quickstartに記載されている内容と同様ですが・・・
付属のクライアントツールでデータの登録と取得、削除を試してみます。

ポート番号6666でサーバーが起動しているので、そこに接続。


###接続には多少時間がかかります。表示が出るまで待ちます。
# bin/voldemort-shell.sh test tcp://localhost:6666
[2010-04-17 14:13:46,696 voldemort.client.DefaultStoreClient] INFO bootstrapping metadata.
Established connection to test via tcp://localhost:6666

###putでデータの登録 put key valueの形式です。
> put "hello" "world"

###getでデータの取得 get keyの形式です。
> get "hello"
version(0:1): "world"

### deleteでデータの削除 delete keyの形式です。
> delete "hello"

### 存在しないキーのデータを取得しようとすると、nullが帰ってきます。
> get "hello"
null

### exitでクライアントツールを終了します。
> exit
k k thx bye.





サンプルどおりですが、動いてくれることを確認しました。
次にkeyやvalueに日本語が使えるか試してみます。


> put "日本語" "通るかな?"
> get "日本語"
version(0:1): "/Kj"
> delete "日本語"
> get "日本語"
null



表示が文字化けしてしまいましたが、ちゃんと検索は行えているようなので
工夫してやれば日本語も使えそうです。



getしたとき、versionが表示されています。
気になったので同じキーで登録して調べてみました。

こんな動きになります。


> put "key" "value0"
> get "key"
version(0:1): "value0"

### 同じキーで登録すると、versionの数字が増える
> put "key" "value1"
> get "key"
version(0:2): "value1"
> put "key" "value2"
> get "key"
version(0:3): "value2"

### 削除すると、一世代戻るわけではなく完全に削除される
> delete "key"
> get "key"
null

### 再度、同じキーで登録すると、versionは1に戻る
> put "key" "value4"
> get "key"
version(0:1): "value4"




versionについては、後日詳しく調べてみたいと思います。




サーバーの終了




# bin/voldemort-server.sh config/single_node_cluster > /tmp/voldemort.log &



このように、バックグラウンドで実行しているので、


# fg



でフォアグラウンドに戻して、Ctrl + Cで終了できます。






とりあえず、起動と動作確認が行えたので、別端末からの
アクセスを試してみたいと思います。






テーマ:データベース - ジャンル:コンピュータ

  1. 2010/04/19(月) 12:10:52|
  2. Voldemort
  3. | トラックバック:0
  4. | コメント:0
  5. | 編集
前のページ