VoldemortにJavaからアクセスする例。
|
Voldemortのクライアントプログラムのコンパイル・実行に必要なjarファイルは以下の通り。
| jarファイル | 備考 | |
|---|---|---|
| C:\voldemort-0.80.2\dist\ | voldemort-0.80.2.jar | ↓ソースの場所(Eclipseで添付可能) C:/voldemort-0.80.2/dist/voldemort-0.80.2-src.jar あるいは C:/voldemort-0.80.2/src |
| resources | コンパイルには不要だが、このディレクトリーを加えておくと そこにあるlog4j.propertiesが実行時に使われる。 |
|
| voldemort-test-0.80.2.jar | コンパイルには不要、実行には必要。 | |
| C:\voldemort-0.80.2\lib\ | *.jar | |
import voldemort.client.ClientConfig; import voldemort.client.SocketStoreClientFactory; import voldemort.client.StoreClient; import voldemort.client.StoreClientFactory; import voldemort.versioning.Versioned;
public class VoldemortSample {
public static void main(String[] args) {
// ストア(テーブル)名と接続先
String storeName = "test";
String bootstrapUrl = "tcp://localhost:6666";
ClientConfig clientConfig = new ClientConfig().setBootstrapUrls(bootstrapUrl);
StoreClientFactory factory = new SocketStoreClientFactory(clientConfig);
try {
StoreClient<String, String> client = factory.getStoreClient(storeName);
Versioned<String> value = client.get("hello");
if (value != null) {
System.out.println(value.getValue());
}
} finally {
factory.close();
}
}
}
StoreClientFactoryを生成し、そこからストアアクセス用のclientを取得する。
MockStoreClientFactoryというファクトリークラスもあって、それはDB接続を伴わない一時的なストア用で、テストに使うのに便利らしい。
clientの型は、上記の例ではStoreClient<String, String>にしている。つまりキーの型がStringで値の型もString。
これは、stores.xmlでキーも値もstringとして定義されているから。
なお、Javaの文法的にはジェネリクスのメソッドのみに型引数を適用する機能を使って自分でStringを指定しているだけで、“Java(ソース)上のどこかで定義されていて自動的にStringになっている”という訳では無い。ObjectでもIntegerでもコンパイルは通る。が、当然、一致しないクラスであれば実行時にキャストできなくて例外が発生する。
Voldemortのデータを操作する為のメソッド(0.80.2)。
| コーディング例 | 備考 | |
|---|---|---|
| 値の取得 (get) |
String key = "hello"; Versioned<String> versioned = client.get(key); if (versioned != null) { String value = versioned.getValue(); } |
最新バージョンの値を取得する。 値が取得できない場合はnullが返る。 |
String key = "hello"; Versioned<String> versioned = client.get(key); if (versioned != null) { Version ver = versioned.getVersion(); System.out.println(ver.toString()); VectorClock clock = (VectorClock) ver; System.out.println(clock.getMaxVersion()); System.out.println(new Date(clock.getTimestamp())); List<ClockEntry> list = clock.getEntries(); for (ClockEntry ce : list) { System.out.println(ce.getNodeId() + " : " + ce.getVersion()); } } |
バージョン情報を取得する例。 過去の履歴が取れるわけではなく、複数ノードのバージョンが取れるっぽい。 |
|
| 複数キーの取得 (getall) |
List<String> keys = new ArrayList<String>();
keys.add("hello");
keys.add("foo");
keys.add("abc");
Map<String, Versioned<String>> values = client.getAll(keys);
for (Entry<String, Versioned<String>> entry : values.entrySet()) {
String key = entry.getKey();
Versioned<String> versioned = entry.getValue();
String value = versioned.getValue();
System.out.println(key + "=" + value);
}
|
複数のキーを指定して値を取得する。 キーが存在しない場合は返り値のマップには何も入らない。(エントリー自体が無い) 1つも取れなかった場合は空のマップが返る。 |
| 値の登録 (put) |
String key = "hello"; String value = "world"; client.put(key, value); |
DBから該当キーの最新バージョンを取得し、 存在すればその次の新しいバージョンとして値を登録する。 無ければ値を新規登録する。 内部では最終的にput(Key, Versioned)を呼んでいる。 |
| 値の登録 (バージョン付き) |
String key = "hello"; String value = "world"; Versioned<String> versioned = client.get(key); versioned.setObject(value); client.put(key, versioned); |
指定されたバージョンで値を登録する。 setObject()した時点では、変数内のバージョン値は変更されない。 DB内のバージョンが指定より新しくなっていると例外が発生して登録できない。 (↓ver9で登録しようとしたが、DBが既にver10になっていた場合のメッセージ) voldemort.versioning.ObsoleteVersionException: Key
68656c6c6f version(0:10) is obsolete, it is no greater than the current
version of version(0:10). |
| 値の登録 (バージョン確認エラーなし) |
String key = "hello"; String value = "world"; Versioned<String> versioned = client.get(key); versioned.setObject(value); client.putIfNotObsolete(key, versioned); |
基本的にはバージョン付きのput()と同じだが、 DB内のバージョンの方が新しくても例外は発生しない。 (データは登録はされず、DB内の新バージョンのデータの方が有効) |
| キーの削除 (delete) |
String key = "hello"; client.delete(key); |
キー(と値)を削除する。 |
| キーの削除 (バージョン付き) |
String key = "hello"; Versioned<String> versioned = client.get(key); if (versioned != null) { Version ver = versioned.getVersion(); client.delete(key, ver); } |
キー(と値)を削除する。 指定されたバージョンより新しいバージョンがDB内に存在した場合、そのデータは削除されない。 |
| ノード情報の取得 (preflist) |
String key = "hello"; List<Node> nodes = client.getResponsibleNodes(key); FailureDetector fd = factory.getFailureDetector(); for (Node node : nodes) { System.out.println("Node " + node.getId()); System.out.println("host: " + node.getHost()); System.out.println("port: " + node.getSocketPort()); System.out.println("available: " + fd.isAvailable(node)); System.out.println("last checked: " + new Date(fd.getLastChecked(node))); } |
指定されたキーに関するノード情報を取得する。 キーが存在していなくても情報が返るが、そのキーを追加する際の情報になるから? |
| ノード数の取得 |
FailureDetector fd = factory.getFailureDetector(); System.out.println(fd.getNodeCount()); System.out.println(fd.getAvailableNodeCount()); |
ノード数を取得する。 |
Voldemortではストアのキーと値の型を定義することが出来るが、そのひとつがJava標準のシリアライズ。[2010-06-05]
<store>
<name>test2</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>java-serialization</type>
</value-serializer>
</store>
put・getする時は、ただ単にシリアライズ可能クラスを指定するだけ。
// ストア(テーブル)名と接続先
String storeName = "test2";
String bootstrapUrl = "tcp://localhost:6666";
StoreClientFactory factory = new SocketStoreClientFactory(new ClientConfig().setBootstrapUrls(bootstrapUrl));
try {
StoreClient<String, SampleBean> client = factory.getStoreClient(storeName);
{
SampleBean bean = new SampleBean();
bean.setId(123);
bean.setStr("sample");
client.put("key", bean);
}
{
Versioned<SampleBean> versioned = client.get("key");
SampleBean bean = versioned.getValue();
System.out.println(bean);
}
} finally {
factory.close();
}
public class SampleBean implements Serializable {
private static final long serialVersionUID = 1L;
protected int id;
protected String str;
〜
}