VPC上のElastiCacheを試してみたの記事のように、VPC上にElastiCacheが追加されました。
しかし、キャッシュクラスタはAZをまたがることができず、また、ノード毎にエンドポイントが
用意されているので、キーの分散(同じキーは同じサーバへ)は自分で行う必要があります。
このキーの分散をアプリ側で行うのではなく、インフラ(ミドルウェア)で対応できないかと調べてみたところ、
下記のようなプロダクトがありました。
twemproxy (pronounced two-em-proxy), aka nutcracker
is a fast and lightweight proxy for memcached and redis protocol.
It was primarily built to reduce the connection count
on the backend caching servers.twemproxy(トゥーエンプロキシーと発音)はnutcrackerとも呼ばれ、
memcachedとredisのプロトコルのための高速で軽量なプロキシーです。
バックエンド(キャッシュ)サーバへの接続数を減少させるために作られました。
これは文字通り、Twitterでも使われているプロダクトのようです。
そして、特長の一つに下記が挙がっています。
Supports multiple hashing modes including consistent hashing and distribution.
Consistent Hashingに分散を含む多くのハッシュ方法をサポートしています。
Consistent Hashingに関しては、第4回 memcachedの分散アルゴリズム:memcachedを知り尽くすの記事が
非常によく解説されており、一読をお勧めします。
要するにtwemproxyを使うことで、キーの分散(同じキーは同じサーバへ)をミドルウェアレベルで
実現可能となります。
そこで、下記のような環境を構築してみますが、ElastiCacheの構築は最初に紹介したブログ記事で構築できるので、
今回はEC2上にtwemproxyをインストールするところから始めます。
○Twemproxyをインストールするための準備
Twemproxyをインストールする時に、CentOS(6.3)のyumでインストールできるautoconfはバージョンが古ので、
その周辺も含め、最新版をインストールします。
・autoconfのインストール
# curl -OL http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz
# tar xvzf autoconf-2.69.tar.gz
# cd autoconf-2.69
# ./configure
# make
# make install
・automakeのインストール
# curl -OL http://ftp.gnu.org/gnu/automake/automake-1.12.tar.gz
# tar xvzf automake-1.12.tar.gz
# cd automake-1.12
# ./configure
# make
# make install
・libtoolのインストール
# curl -OL http://ftp.jaist.ac.jp/pub/GNU/libtool/libtool-2.4.2.tar.gz
# tar xvzf libtool-2.4.2.tar.gz
# cd libtool-2.4.2
# ./configure
# make
# make install
○Twemproxyをインストール
# curl -OL https://github.com/twitter/twemproxy/archive/v0.2.2.zip
# unzip v0.2.2.zip
# cd twemproxy-0.2.2/
# /usr/local/bin/autoreconf -fvi
# ./configure
# make
# make install
○Twemproxyの設定と起動
はじめに、下記のような設定ファイルを作成します。
・nutcracker.yml
cache:
listen: 0.0.0.0:11211
hash: fnv1a_64
distribution: ketama
servers:
- 10.100.64.217:11211:1
- 10.100.64.190:11211:1
- 10.100.65.53:11211:1
- 10.100.65.181:11211:1
- 10.100.66.110:11211:1
- 10.100.66.56:11211:1
- listen
- IPアドレスとポートを指定します。
- hash
- ハッシュ方法を指定します。(詳細については要調査)
- distribution
- 分散方法を指定します。(ketamaがConsistent Hashingです)
- servers
- サーバ:ポート:重みで指定します。
ただし、サーバはDNS名が利用できなかったのでIPアドレスを引いて指定しています。
- サーバ:ポート:重みで指定します。
次に、下記でTwemproxyを起動します。
/usr/local/bin/nutcracker -d -i 1000 -c ./nutcracker.yml
- -d
- デーモンとして起動します。
- -i
- 統計情報を集めるインターバルです。
- -c
- 利用する設定ファイルです。
IPアドレスで指定してしまうと、変更してしまった時に、HAProxyをDNS名で指定したバックエンドのIPアドレスが
変わったらリロードするの記事で紹介したような対応が必要になります。
○動作確認
一度保存した値は、取得する時も同じサーバから取得できていることがわかります。
# telnet 127.0.0.1 22222
Trying 127.0.0.1...
Connected to 127.0.0.1.
Escape character is '^]'.
{
"cache": {
"10.100.64.190:11211:1": {
"in_queue": 0,
"in_queue_bytes": 0,
"out_queue": 0,
"out_queue_bytes": 0,
"request_bytes": 23,
"requests": 4,
"response_bytes": 10,
"responses": 4,
"server_connections": 1,
"server_eof": 0,
"server_err": 0,
"server_timedout": 0
},
"10.100.64.217:11211:1": {
"in_queue": 0,
"in_queue_bytes": 0,
"out_queue": 0,
"out_queue_bytes": 0,
"request_bytes": 51,
"requests": 3,
"response_bytes": 69,
"responses": 3,
"server_connections": 1,
"server_eof": 0,
"server_err": 0,
"server_timedout": 0
},
"10.100.65.181:11211:1": {
"in_queue": 0,
"in_queue_bytes": 0,
"out_queue": 0,
"out_queue_bytes": 0,
"request_bytes": 0,
"requests": 0,
"response_bytes": 0,
"responses": 0,
"server_connections": 0,
"server_eof": 0,
"server_err": 0,
"server_timedout": 0
},
"10.100.65.53:11211:1": {
"in_queue": 0,
"in_queue_bytes": 0,
"out_queue": 0,
"out_queue_bytes": 0,
"request_bytes": 0,
"requests": 0,
"response_bytes": 0,
"responses": 0,
"server_connections": 0,
"server_eof": 0,
"server_err": 0,
"server_timedout": 0
},
"10.100.66.110:11211:1": {
"in_queue": 0,
"in_queue_bytes": 0,
"out_queue": 0,
"out_queue_bytes": 0,
"request_bytes": 96,
"requests": 7,
"response_bytes": 155,
"responses": 7,
"server_connections": 1,
"server_eof": 0,
"server_err": 0,
"server_timedout": 0
},
"10.100.66.56:11211:1": {
"in_queue": 0,
"in_queue_bytes": 0,
"out_queue": 0,
"out_queue_bytes": 0,
"request_bytes": 21,
"requests": 2,
"response_bytes": 5,
"responses": 2,
"server_connections": 1,
"server_eof": 0,
"server_err": 0,
"server_timedout": 0
},
"client_connections": 0,
"client_eof": 0,
"client_err": 3,
"forward_error": 0,
"fragments": 3,
"server_ejects": 0
},
"service": "nutcracker",
"source": "ip-10-100-0-236",
"timestamp": 1356201522,
"uptime": 17075,
"version": "0.2.2"
}
Connection closed by foreign host.