さらさらとApache Geodeのソースツリーやドキュメントを眺めていて、Apache GeodeをMemcachedやRedisとしても使えそうだったので、試してみました。
Moving from memcached to gemcached - Geode - Apache Software Foundation
Geode Redis Adapter - Geode - Apache Software Foundation
「gemcached」、ときましたか…。
RedisAdapterは、GemFireの頃にはなかったのかな?
今回、Apache Geode 1.0.0-incubating.M1を使って、これらの機能を動かしてみます。
gemcached
Server起動時に、以下のようなオプションを付けてあげればMemcachedとして使えるようになります。
※Locatorは起動済みとします
gfsh>start server --name=server --memcached-port=11211 --memcached-bind-address=localhost --memcached-protocol=BINARY
「memcached-bind-address」は付けなくてもいいんですが、デフォルトだとそのホストのIPアドレスでリッスンしようとするので、localhostとかでつなげたければ明示してあげる必要があります。
ASCII、BINARYプロトコル、両方対応してるみたいですね。すごい。
「gemcached」というRegionにデータが保存されるようなので、細かく設定する場合はキャッシュの設定ファイル用意するっぽい感じです。
https://github.com/apache/incubator-geode/blob/rel/v1.0.0-incubating.M1/gemfire-core/src/main/java/com/gemstone/gemfire/memcached/GemFireMemcachedServer.java#L76
GeodeをMemcachedサーバーとして使うことで、通常のMemcachedとは異なり「cache-aside」、「write-through」が使えたり、可用性を高められることが利点みたいです。
とりあえず、クライアント側のサンプルも書いてみます。
<dependency> <groupId>net.spy</groupId> <artifactId>spymemcached</artifactId> <version>2.12.0</version> </dependency>
spymemcached、あとはJUnitとAssertJを利用します。
確認コード。
src/test/java/org/littlewings/geode/GeodeMemcachedTest.java
package org.littlewings.geode; import java.io.IOException; import java.util.concurrent.TimeUnit; import net.spy.memcached.AddrUtil; import net.spy.memcached.BinaryConnectionFactory; import net.spy.memcached.MemcachedClient; import org.junit.Test; import static org.assertj.core.api.Assertions.assertThat; public class GeodeMemcachedTest { @Test public void test() throws IOException, InterruptedException { MemcachedClient client = null; try { client = new MemcachedClient(new BinaryConnectionFactory(), AddrUtil.getAddresses("localhost:11211")); client.set("key1", 5, "value1"); assertThat(client.get("key1")) .isEqualTo("value1"); TimeUnit.SECONDS.sleep(5); assertThat(client.get("key1")) .isNull(); } finally { if (client != null) { client.shutdown(); } } } }
OKそうですね。
Redis Adapter
続いて、Redisとして使ってみます。Serverを、こんな感じで起動。
※Locatorは起動済みとします
gfsh>start server --name=server --redis-port=6379 --redis-bind-address=localhost
「redis-bind-address」にlocalhostを指定しているのは、Memcachedの時と同じ理由です。
サポートしているコマンドはWikiに書いてあるので、こちらを読みましょう。
https://cwiki.apache.org/confluence/display/GEODE/Geode+Redis+Adapter
Redis Adapterが利用するRegionは…なんかすごい名前な気がします。
https://github.com/apache/incubator-geode/blob/rel/v1.0.0-incubating.M1/gemfire-core/src/main/java/com/gemstone/gemfire/redis/GemFireRedisServer.java#L223-L239
では、動作確認してみます。Maven依存関係。
<dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>2.8.0</version> </dependency>
Jedisを使います。
確認コード。
src/test/java/org/littlewings/geode/GeodeRedisTest.java
package org.littlewings.geode; import java.util.HashMap; import java.util.Map; import org.junit.Test; import redis.clients.jedis.Jedis; import static org.assertj.core.api.Assertions.assertThat; public class GeodeRedisTest { @Test public void test() { try (Jedis jedis = new Jedis("localhost", 6379, 10 * 000)) { jedis.set("key1", "value1"); assertThat(jedis.get("key1")) .isEqualTo("value1"); jedis.lpush("lkey1", "lvalue1", "lvalue2"); assertThat(jedis.lpop("lkey1")) .isEqualTo("lvalue2"); assertThat(jedis.lpop("lkey1")) .isEqualTo("lvalue1"); jedis.sadd("skey1", "svalue1", "svalue2"); assertThat(jedis.scard("skey1")) .isEqualTo(2L); jedis.zadd("zkey1", 1.0, "zvalue1"); jedis.zadd("zkey1", 2.0, "zvalue2"); assertThat(jedis.zcard("zkey1")) .isEqualTo(2L); Map<String, String> data = new HashMap<>(); data.put("key1", "value1"); data.put("key2", "value2"); jedis.hmset("hmkey1", data); assertThat(jedis.hgetAll("hmkey1")) .isEqualTo(data); } } }
うちの環境だとちょっと時間がかかることがあり(特に起動直後)ReadTimeoutすることがあったので、ソケットのタイムアウトを伸ばしています…。
動作自体は、この範囲だと普通に使えそうな感じで。
まとめ
とりあえず、本線の機能でもないのに気になったので試してみた感じです。これ、たぶん組み込みでも使えるんだろうなぁと思うのですが、それはまたの機会に。