ちょっとした好奇心で。
memcachedって実は使ったことがないのですが、InfinispanとHazelcastはmemcachedサーバとして使えるのでこれをちょっと試してみようと思います。Infinispanの方はtelnetで試したことはありますが、ここはJava系のクライアントで使ってみます。
クライアントには、spymemcachedを選びました。
spymemcached
http://code.google.com/p/spymemcached/
サンプル
http://code.google.com/p/spymemcached/wiki/Examples
Javadoc
http://www.couchbase.com/autodocs/couchbase-java-client-1.2.0/index.html
JavadocはなんかCouchbaseの方に統合されていたっぽいので、正しいバージョンがどれなのかはよくわかりません。
とりあえず、Maven Centralで確認するとspymemcachedの現時点での最新バージョンは2.10.1のようです。
build.sbt
name := "memcached-client" version := "0.0.1-SNAPSHOT" scalaVersion := "2.10.3" organization := "littlewings" libraryDependencies += "net.spy" % "spymemcached" % "2.10.1"
サンプルプログラム。
src/main/scala/SimpleMemcachedClient.scala
import java.net.InetSocketAddress import net.spy.memcached.{AddrUtil, BinaryConnectionFactory, MemcachedClient} object SimpleMemcachedClient { def main(args: Array[String]): Unit = { val client = new MemcachedClient(new InetSocketAddress("localhost", 11211)) try { for (i <- 1 to 10) client.set(s"key$i", 3, s"value$i") // Expireは3秒 for (i <- 1 to 10) require(client.get(s"key$i") == s"value$i") // 5秒間待機 println("Sleeping...") Thread.sleep(5 * 1000L) for (i <- 1 to 10) require(client.get(s"key$i") == null) // 5秒後は、すべてExpire済み } finally { client.shutdown() } } }
バイナリプロトコルとか試してみたのですが、いろいろあって結局この程度になりました。Expireを3秒で10個の要素を入れて、最初に取り出してスリープ入れて、要素がなくなったことを確認するプログラムです。
では、memcachedサーバを用意します。
Infinispan
オフィシャルサイトから、Server用のモジュールをダウンロードします。
http://infinispan.org/download/
現時点での最新安定版は、5.3.0.Finalです。
適当な場所に展開して
$ unzip infinispan-server-5.3.0.Final-bin.zip
$ infinispan-server-5.3.0.Final/bin/standalone.sh
起動時のログをよくよく見ると、
23:54:43,991 INFO [org.jboss.as.clustering.infinispan] (MSC service thread 1-4) JBAS010281: Started memcachedCache cache from local container
とか
23:54:44,059 INFO [org.infinispan.server.endpoint] (MSC service thread 1-4) JDGS010000: MemcachedServer starting 23:54:44,066 INFO [org.infinispan.server.endpoint] (MSC service thread 1-4) JDGS010001: MemcachedServer listening on 127.0.0.1:11211
とか言われていて、memcachedとして起動しているコンテナがあることが確認できます。
では先ほどのプログラムを実行。
> run [info] Running SimpleMemcachedClient 2013-10-17 23:57:44.000 INFO net.spy.memcached.MemcachedConnection: Added {QA sa=localhost/127.0.0.1:11211, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=0} to connect queue 2013-10-17 23:57:44.006 INFO net.spy.memcached.MemcachedConnection: Connection state changed for sun.nio.ch.SelectionKeyImpl@1f399537 Sleeping... 2013-10-17 23:57:49.092 INFO net.spy.memcached.MemcachedConnection: Shut down memcached client [success] Total time: 5 s, completed 2013/10/17 23:57:49
requireで確認しているので、結果が特に表示されませんが…一応、ちゃんと動作しています。
Hazelcast
続いて、Hazelcast。こちらはInfinispanと違ってServer用のモジュールなどないので、簡単なプログラムを作成します。
memcached_server.clj
(require '[leiningen.exec :as exec]) (exec/deps '[[com.hazelcast/hazelcast "3.1"]]) (ns hazelcast-memcached (:import (com.hazelcast.config Config NetworkConfig) (com.hazelcast.core Hazelcast HazelcastInstance))) (try (let [^Config config (. (Config.) setNetworkConfig (. (NetworkConfig.) setPort 11211)) ^HazelcastInstance hazelcast (Hazelcast/newHazelcastInstance config)] (println "Server Startup.") ;; Enter待ち (read-line) ;; HazelcastInstanceをシャットダウン (.. hazelcast getLifecycleService shutdown)) ;; 全Hazelcastインスタンスをシャットダウン (finally (Hazelcast/shutdownAll)))
めっちゃ簡単なプログラムです。Enterキーを入力するか、シグナル等で止めてしまうまで浮いたままのサーバとなります。
が、ポートをInfinispanの時と合わせるために、リッスンポートを変更しています。
(let [^Config config (. (Config.) setNetworkConfig (. (NetworkConfig.) setPort 11211))
デフォルトポートは、5701ですので。
では、起動。lein-execプラグインを使用しています。
$ lein exec memcached_server.clj 10 18, 2013 12:00:38 午前 com.hazelcast.instance.DefaultAddressPicker 情報: Prefer IPv4 stack is true. 10 18, 2013 12:00:38 午前 com.hazelcast.instance.DefaultAddressPicker 情報: Picked Address[192.168.129.128]:11211, using socket ServerSocket[addr=/0:0:0:0:0:0:0:0,localport=11211], bind any local is true 10 18, 2013 12:00:38 午前 com.hazelcast.system 情報: [192.168.129.128]:11211 [dev] Hazelcast Community Edition 3.1 (20131011) starting at Address[192.168.129.128]:11211 10 18, 2013 12:00:38 午前 com.hazelcast.system 情報: [192.168.129.128]:11211 [dev] Copyright (C) 2008-2013 Hazelcast.com 10 18, 2013 12:00:38 午前 com.hazelcast.instance.Node 情報: [192.168.129.128]:11211 [dev] Creating MulticastJoiner 10 18, 2013 12:00:38 午前 com.hazelcast.core.LifecycleService 情報: [192.168.129.128]:11211 [dev] Address[192.168.129.128]:11211 is STARTING 10 18, 2013 12:00:43 午前 com.hazelcast.cluster.MulticastJoiner 情報: [192.168.129.128]:11211 [dev] Members [1] { Member [192.168.129.128]:11211 this } 10 18, 2013 12:00:43 午前 com.hazelcast.core.LifecycleService 情報: [192.168.129.128]:11211 [dev] Address[192.168.129.128]:11211 is STARTED Server Startup.
先ほどのspymemcachedを使ったプログラムも、同様に動作させることができます。
> run [info] Running SimpleMemcachedClient 2013-10-18 00:01:19.537 INFO net.spy.memcached.MemcachedConnection: Added {QA sa=localhost/127.0.0.1:11211, #Rops=0, #Wops=0, #iq=0, topRop=null, topWop=null, toWrite=0, interested=0} to connect queue 2013-10-18 00:01:19.545 INFO net.spy.memcached.MemcachedConnection: Connection state changed for sun.nio.ch.SelectionKeyImpl@58cc0b23 Sleeping... 2013-10-18 00:01:24.781 INFO net.spy.memcached.MemcachedConnection: Shut down memcached client [success] Total time: 5 s, completed 2013/10/18 0:01:24
ホントに、ちょっと使ってみました的なネタでした。
InfinispanやHazelcastのようなデータグリッドを使うと、分散できたり永続化できたりしていろいろ便利?でもまあ、実際にリモートアクセスするならInfinispanならHot Rod使うでしょうし、HazelcastならNative Client使いますよねー。