JavaからMemcachedを読み書きする。キーと値の一覧を取得する。
検索したら、Memcachedに、telnetで接続して、コマンドラインで、キー一覧取得というのをやっているのを見かけた。ほかにも、PHPやRubyやPerlで同じようなことをやっているのも見かけた。
自分もまねして、JavaのクライアントからMemcachedに登録したデータのキーと値の一覧の取得をやってみる。
ちなみに、本家のWebサイトを見ると、すべてのキー取得はできないとある
Google Code Archive - Long-term storage for Google Code Project Hosting.
With memcached, you can't list all keys
ここで、やる方法も問題あるのかな。。。。まあ、いいや。練習と開発用の小さいツールがほしいだけだから。
環境は構築済み
memcachedをUbuntu上で動かす - kaishitaeiichiの日記
Javaのmemcachedクライアントのライブラリもここでためしてある。
F:\Data\Eclipse\workspaces\Java\032-01 Memcached-Java-Client>tree /F フォルダ パスの一覧 ボリューム シリアル番号は 00680063 781F:C3ED です F:. │ .classpath │ .project │ ├─.settings │ org.eclipse.jdt.core.prefs │ ├─classes │ log4j.properties │ MyClass.class │ MyMemcachedClient.class │ TestBean.class │ ├─lib | commons-lang3-3.0.1.jar │ commons-pool-1.5.6.jar │ java_memcached-release_2.6.3.jar │ slf4j-api-1.6.1.jar │ slf4j-log4j12-1.6.1.jar │ slf4j-simple-1.6.1.jar │ └─src log4j.properties MyClass.java MyMemcachedClient.java TestBean.java
Memcached-Java-Client/HOWTO.txt at master · gwhalin/Memcached-Java-Client · GitHubこのソースコードをもとにした。
import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.builder.ToStringBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.danga.MemCached.MemCachedClient; import com.danga.MemCached.SockIOPool; public class MyMemcachedClient { private Logger logger = LoggerFactory.getLogger(MyMemcachedClient.class); private MemCachedClient mcc = new MemCachedClient(); private Pattern pattern = Pattern.compile("items:(.+):number"); public MyMemcachedClient() { String[] servers = { "192.168.2.50:11211" }; Integer[] weights = { 1 }; SockIOPool pool = SockIOPool.getInstance(); pool.setServers(servers); pool.setWeights(weights); pool.setInitConn(5); pool.setMinConn(5); pool.setMaxConn(250); pool.setMaxIdle(1000 * 60 * 60 * 6); pool.setMaintSleep(30); pool.setNagle(false); pool.setSocketTO(3000); pool.setSocketConnectTO(0); pool.initialize(); } public void setAndGetExampleData() { mcc.set("bar", "This is a test String"); String bar = (String) mcc.get("bar"); System.out.println("bar=" + bar); mcc.set("testBean", new TestBean()); TestBean testBean = (TestBean) mcc.get("testBean"); System.out.println("testBean=" + testBean.toString()); } public void showKeyAndValue() { List<String> keyList = getKeyList(); for (String key : keyList) { Object value = this.mcc.get(key); String valueAsString = null; if (StringUtils.contains(value.getClass().getSimpleName(), "Dto") || StringUtils.contains(value.getClass().getSimpleName(), "Bean")) { valueAsString = ToStringBuilder.reflectionToString(value); } else { valueAsString = ObjectUtils.toString(value); } String keyAndValue = MessageFormat.format("key={0} value={1}", key, valueAsString); System.out.println(keyAndValue); } } public List<String> getKeyList() { List<String> itemsNumberList = new ArrayList<String>(); Map<String, Map<String, String>> statsItems = this.mcc.statsItems(); for (Map.Entry<String, Map<String, String>> statsItemsEntry : statsItems .entrySet()) { String key = statsItemsEntry.getKey(); Map<String, String> statsItemsValue = statsItemsEntry.getValue(); for (String itemsNumber : statsItemsValue.keySet()) { Matcher matcher = this.pattern.matcher(itemsNumber); if (matcher.find()) { itemsNumberList.add(matcher.group(1)); } } } List<String> keyList = new ArrayList<String>(); for (String itemsNumber : itemsNumberList) { //とりあえず、1000にしたけど、必要に応じて増やす? //key-valueといわれても、Memcached内部のデータ構造がわかってない //どうなっているんだろう。 Map<String, Map<String, String>> statsCacheDump = this.mcc .statsCacheDump(Integer.valueOf(itemsNumber), 1000); for (Map.Entry<String, Map<String, String>> statsCacheDumpEntry : statsCacheDump .entrySet()) { String key = statsCacheDumpEntry.getKey(); Map<String, String> statsCacheDumpValue = statsCacheDumpEntry .getValue(); keyList.addAll(statsCacheDumpValue.keySet()); } } return keyList; } private void debug(String name, Map<?, ?> map) { for (Map.Entry<?, ?> entry : map.entrySet()) { String log = MessageFormat.format("key={0} value={1}", entry.getKey(), entry.getValue()); logger.debug(log); } } public static void main(String[] args) { MyMemcachedClient client = new MyMemcachedClient(); client.setAndGetExampleData(); client.showKeyAndValue(); } }
実行結果、コンソール出力
bar=This is a test String testBean=TestBean [stringField=a, integerField=0] key=bar value=This is a test String key=testBean value=TestBean@1a457b6[stringField=a,integerField=0]
おおー、うまくいった。
Memcachedで、一覧取得、全件取得ってのが、やりたかったわけで、もっと簡単にはできないのだろうか
みんな、実際、どうしているんだろうな。開発中あると便利だと思うんだが。データ量が増えると、全件取得なんてのは、やっぱり、実際的でないのか。
MySQLとか、RDBだったら、selectで全件取得はできるけど、やっぱり、データが多いときは、あんまりうれしくないしな。