MySQL 5.6の RC 版が出ましたね。魅力的な機能が満載で皆さんwktkしていることと思います。早速、個人的に気になっていた memcached plugin を試してみました。
最初に結論から言いますが、現時点 (5.6.7rc) では HandlerSocket の代わりに使えるようなものではなさそうです。
memcached protocol でアクセスできるのは全体で 1 テーブルのみ訂正: namespace という仕組みで複数テーブルにmapが可能ですテーブルの文字コードは latin1 である必要がある
【2012-11-22 追記】5.6.8RCでは、文字コードが latin1 であるという制限は撤廃されました
「MySQL のテーブルに memcached protocol でアクセスできる」というよりは、「memcached のストレージを InnoDB にできる」ようなものと考えていただければよいのではないかと。
使ってみる
では使ってみます。といってもソースに含まれる plugin/innodb_memcached/README-innodb_memcached のままですが…
設定のための SQL を流し込んで、
$ mysql < scripts/innodb_memcached_config.sql
plugin を読み込みます。
mysql> install plugin daemon_memcached soname "libmemcached.so"; mysql> show plugins; +----------------------------+----------+--------------------+-----------------+---------+ | Name | Status | Type | Library | License | +----------------------------+----------+--------------------+-----------------+---------+ (略) | daemon_memcached | ACTIVE | DAEMON | libmemcached.so | GPL | +----------------------------+----------+--------------------+-----------------+---------+
これで mysqld が TCP/UDP 11211 を listen します。設定は innodb_memcache というデータベースに保存されます。
mysql [localhost] (innodb_memcache) > show tables; +---------------------------+ | Tables_in_innodb_memcache | +---------------------------+ | cache_policies | | config_options | | containers | +---------------------------+ 3 rows in set (0.00 sec) mysql [localhost] (innodb_memcache) > desc containers; +------------------------+--------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------------------+--------------+------+-----+---------+-------+ | name | varchar(50) | NO | PRI | NULL | | | db_schema | varchar(250) | NO | | NULL | | | db_table | varchar(250) | NO | | NULL | | | key_columns | varchar(250) | NO | | NULL | | | value_columns | varchar(250) | YES | | NULL | | | flags | varchar(250) | NO | | 0 | | | cas_column | varchar(250) | YES | | NULL | | | expire_time_column | varchar(250) | YES | | NULL | | | unique_idx_name_on_key | varchar(250) | NO | | NULL | | +------------------------+--------------+------+-----+---------+-------+ 9 rows in set (0.00 sec) mysql [localhost] (innodb_memcache) > select * from containers\G *************************** 1. row *************************** name: aaa db_schema: test db_table: demo_test key_columns: c1 value_columns: c2 flags: c3 cas_column: c4 expire_time_column: c5 unique_idx_name_on_key: PRIMARY 1 row in set (0.00 sec)
containers というテーブルに、memcached plugin 経由で実際にアクセスするテーブルの情報を保存します。
この例だと、test.demo_test というテーブルで key が c1, value が c2 に保存される、ということになります。
mysql [localhost] (test) > select * from demo_test; +----+--------------+------+------+------+ | c1 | c2 | c3 | c4 | c5 | +----+--------------+------+------+------+ | AA | HELLO, HELLO | 8 | 0 | 0 | +----+--------------+------+------+------+ 1 row in set (0.00 sec)
telnet で port 11211 に接続して get してみます。
$ telnet localhost 11211 Connected to localhost. get AA VALUE AA 8 12 HELLO, HELLO END
取れましたね! telnet で set してみます。
$ telnet localhost 11211 Connected to localhost. set BB 0 0 3 BBB STORED
mysql [localhost] (test) > select * from demo_test; +----+--------------+------+------+------+ | c1 | c2 | c3 | c4 | c5 | +----+--------------+------+------+------+ | AA | HELLO, HELLO | 8 | 0 | 0 | | BB | BBB | 0 | 2 | 0 | +----+--------------+------+------+------+ 2 rows in set (0.00 sec)
保存されています。
軽くベンチマーク
memslap を使ってみました。
$ memslap --servers=127.0.0.1:11211 --test set Took 14.781 seconds to load data $ memslap --servers=127.0.0.1:11211 --test get Took 1.232 seconds to read data
本物の memcached
$ memslap --servers=127.0.0.1:11222 --test set Took 0.533 seconds to load data $ memslap --servers=127.0.0.1:11222 --test get Took 0.655 seconds to read data
daemon_memcached_w_batch_size というパラメータで書き込みをまとめて性能を上げることができます。
# my.cnf [mysqld] daemon_memcached_w_batch_size = 100
$ memslap --servers=127.0.0.1:11211 --test set Took 4.512 seconds to load data
memstat の出力
curr_items, total_items, bytes あたりの数値は取れないようです。
$ memstat --servers=127.0.0.1:11211 Server: 127.0.0.1 (11211) pid: 11353 uptime: 286 time: 1349335741 version: 5.6.7-rc pointer_size: 64 rusage_user: 8.724673 rusage_system: 10.740367 curr_items: 0 total_items: 0 bytes: 0 curr_connections: 3 total_connections: 12 connection_structures: 3 cmd_get: 30000 cmd_set: 60000 get_hits: 30000 get_misses: 0 evictions: 0 bytes_read: 0 bytes_written: 0 limit_maxbytes: 67108864 threads: 4
まとめ
普通に動きます が、全体で1テーブルしか使えないとちょっと使いどころが難しいですね。
一応、 innodb_memcache.containers テーブルには name カラムがあって、そのカラムによって読み込む設定を分けるようなことは想定されているようです。が、現状は最初の1行を決めうちで読み込んでいるので、複数行入れても最初の行の設定しか有効になりません。 (訂正): containers の name に入れた値を使って、別テーブルにアクセス可能でした。namespaceを使わずにデフォルトでアクセスするのが最初の1行で定義されているテーブルです。
+------+-----------+------------+-------------+---------------+-------+------------+--------------------+------------------------+ | name | db_schema | db_table | key_columns | value_columns | flags | cas_column | expire_time_column | unique_idx_name_on_key | +------+-----------+------------+-------------+---------------+-------+------------+--------------------+------------------------+ | aaa | test | demo_test | c1 | c2 | c3 | c4 | c5 | PRIMARY | | bbb | test | demo_test2 | c1 | c2 | c3 | c4 | c5 | PRIMARY | +------+-----------+------------+-------------+---------------+-------+------------+--------------------+------------------------+
この状態で、memcached protocol でアクセスする key を @@aaa.foo とすると demo_test.c1='foo' に、@@bbb.foo とすると demo_test2.c1='foo' にアクセスすることができます。