MySQLにmemcachedプラグインをインストールしてJavaからアクセスする

####MySQLにmemcachedプラグインを入れる

######1.libevent-develをインストール

```bin/bash:/bin/bash
# yum -y install libevent-devel
```

######2. my.cnfにmemcacheの設定を追加

```/etc/my.cnf
daemon_memcached_option = "-p11211"
daemon_memcached_engine_lib_name = innodb_engine.so
daemon_memcached_r_batch_size = 1
daemon_memcached_w_batch_size = 1
```

######3.memcachedプラグインをインストールする

```mysql:mysql
mysql> INSTALL PLUGIN daemon_memcached soname "libmemcached.so";
mysql> show plugins;
```
daemon_memcached というプラグインが入ったことを確認

######4.テスト用のテーブルを作成する

```mysql:mysql
mysql> use test
mysql> create table user (id varchar(16), passwd varchar(256), primary key(id)) engine=InnoDB;
mysql> insert into user (id, passwd) values ('user01', '5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8');
```
※insertしたpasswdカラムの値は"password"をsha256したもの

######5.memcache経由でアクセスできるようにする

```mysql:mysql
mysql> insert into innodb_memcache.containers (`name`,`db_schema`,`db_table`,`key_columns`,`value_columns`,`flags`,`cas_column`,`expire_time_column`,`unique_idx_name_on_key`) VALUES ('user', 'test', 'user', 'id', 'passwd',0,0,0,'PRIMARY');
mysql> UNINSTALL PLUGIN daemon_memcached;INSTALL PLUGIN daemon_memcached soname "libmemcached.so";
```
**@@(innodb_memcache.containersのnameカラムの値).keyとしてアクセス可能**
*$ telnet 127.0.0.1 11211* して *get @@user.user01* とタイプした時にsha256の文字列が返ってくればOK

######6.Java側を実装する
↓あたりからspymemcachedをダウンロードするhttp://www.java2s.com/Code/Jar/s/Downloadspymemcached27jar.htm
*※もちろんMavenで対応してもOK*

今回はID,PassをJSONでPOSTした際に、ユーザ登録があった場合には200、無かった(ID,Passが一致しない)場合には401が返ってくるRestAPIをJavaEEのJAX-RSで作成してみた。

```Memcache.java
package memcached;

import java.net.InetSocketAddress;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Map;

import javax.enterprise.context.RequestScoped;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.ResponseBuilder;

import net.spy.memcached.MemcachedClient;

@RequestScoped
@Path("/auth")
@Produces("application/json")
@Consumes("application/json")
public class Memcache {

	@POST
	public Response auth (Map<String, String> param) {
		ResponseBuilder response = null;
		try {
			MemcachedClient memcachedClient = new MemcachedClient (new InetSocketAddress("192.168.56.102", 11211));
			if ( sha256( param.get("password") ).equals( memcachedClient.get( "@@user." + param.get("id") ).toString() ) ) {
				response = Response.status(200);
			} else {
				response = Response.status(401);
			}
		} catch (Exception e) {
			response = Response.status(400);
		}
		return response.build();
	}

	private String sha256(String plaintext) throws Exception{
		MessageDigest md = MessageDigest.getInstance("SHA-256");
		StringBuilder sb = new StringBuilder();
		md.update(plaintext.getBytes());
	    for (byte b : md.digest()) {
	        String hex = String.format("%02x", b);
	        sb.append(hex);
	    }
	    return sb.toString();
	}
}
```

**「value_columns: CHAR、VARCHAR、または BLOB カラムにマップされる必要があります」**とのことで、**JSON型のフィールドをそのままmemcachedで扱うことは不可能**:cry:（telnetしてみると応答はあるけど中身ぐちゃぐちゃ）
→ https://dev.mysql.com/doc/refman/5.6/ja/innodb-memcached-internals.html
CASTすれば大丈夫なのか不明だが、何もせずとも対応できるようにしてくださいな。>Oracleさん

(追記)
generated columnを使って、JSON型のカラムからTEXT型のカラムを生成してvalue_columnsに指定してみた。

``` mysql:mysql
mysql> create table userinfo (id varchar(16), infojson json, userinfo text as (cast(infojson as char) engine=InnoDB;
mysql> insert into innodb_memcache.containers (`name`,`db_schema`,`db_table`,`key_columns`,`value_columns`,`flags`,`cas_column`,`expire_time_column`,`unique_idx_name_on_key`) VALUES ('userinfo', 'test', 'userinfo', 'id', 'userinfo',0,0,0,'PRIMARY');
mysql> UNINSTALL PLUGIN daemon_memcached;INSTALL PLUGIN daemon_memcached soname "libmemcached.so";
```
結果、**NG!**
逆(text型からjson型をgenerated column）なら出来るんだろうけど、json関数使った更新系クエリ使えないから美味しさ半減。。