Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

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

1.libevent-develをインストール
/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> INSTALL PLUGIN daemon_memcached soname "libmemcached.so";
mysql> show plugins;

daemon_memcached というプラグインが入ったことを確認

4.テスト用のテーブルを作成する
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> 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> 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関数使った更新系クエリ使えないから美味しさ半減。。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした