ども、cloudpackかっぱ (@inokara) です。

はじめに

複数の memcached を分散アクセスさせるためのソリューションとして twemproxy 以外のソリューションを探していたところ、mcrouter という Facebook 謹製のツールがあるようなので試してみました。

参考

当初は CentOS 6.5 でセットアップを進めていましたが、folly というライブラリのインストールで m4 マクロのエラーからビルドが通らずに詰んでしまいました…改めてチャレンジできればと考えています。

mcrouter のウンチク、セットアップと動作確認

mcrouter のウンチク

mcrouter は上述の通り Facebook 謹製の memcached プロトコルをスケールさせる機能を持ったミドルウェアで以下のような機能があります。(主な機能を抜粋)

  • ASCII protocol(memcached プロトコルサポート)
  • Connection Pool
  • Multiple hashing schemes
  • Prefix routing
  • Replicated pools

をはじめヘルスチェックやフェイルオーバー、SSL のサポートなどの機能があります。詳しくはこちら「Features · facebook/mcrouter Wiki」やこちら「Home ·facebook/mcrouter Wiki」を御覧ください。

今回は Replicated pools を中心に触っていきたいと思います。

mcrouter のセットアップ

mcrouter には Ubuntu 環境にセットアップできるスクリプトが標準で添付されます。対象は 14.04 ということで Ubuntu 14.04 を Dockerコンテナで用意しておきます。

docker run -t -i ubuntu /bin/bash
root@e75ada9a6323:~/mcrouter/mcrouter/scripts# cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.1 LTS"
root@e75ada9a6323:~/mcrouter/mcrouter/scripts#

git パッケージをインストールします。

apt-get -y install git

mcrouter を git clone してきます。

git clone https://github.com/facebook/mcrouter.git

セットアップスクリプトを実行します

cd mcrouter/mcrouter/scripts
./install_ubuntu_14.04.sh /opt/mcrouter

しばし待ちましょう。
セットアップが終了したらヘルプやバージョンをちょろっと見てみます。

root@e75ada9a6323:~/mcrouter/mcrouter/scripts# /opt/mcrouter/install/bin/mcrouter --version
mcrouter 1.0
root@e75ada9a6323:~/mcrouter/mcrouter/scripts#
root@e75ada9a6323:~/mcrouter/mcrouter/scripts# /opt/mcrouter/install/bin/mcrouter --help
mcrouter 1.0
usage: /opt/mcrouter/install/bin/mcrouter [options] -p port(s) -f config

libmcrouter options:

(略)

memcached のセットアップと起動

セットアップといっても大したことはしません…。CentOS 6.5 のコンテナに yum で memcached をインストールして以下のようなスクリプトを置くだけです。

#!/bin/sh

/usr/bin/memcached -p 11211 -u memcached -m 64 -c 1024 -P /var/run/memcached/memcached.pid

memcached の -d オプションにしばらく気付かずにコンテナが exit0 してしばらく悩みました。すいません。

上記で作成したコンテナを以下のように起動します。

docker run -d -i -p 11211 memcached /root/start.sh

このコマンドを二回実行して二つの memcached コンテナを起動しておきます。

CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                      NAMES
6d36454a6a31        memcached:latest    "/root/start.sh"    22 minutes ago      Up 22 minutes       0.0.0.0:49164->11211/tcp   romantic_fermi
d7681376831a        memcached:latest    "/root/start.sh"    24 minutes ago      Up 24 minutes       0.0.0.0:49163->11211/tcp   reverent_bartik
e75ada9a6323        ubuntu:latest       "/bin/bash"         About an hour ago   Up About an hour                               prickly_curie

mcrouter の設定と起動

mcrouter の設定ファイルは JSON 形式をサポートしており、C++ のコメントアウトや JSONM というマクロもサポートしています。詳しくはドキュメントを御覧ください。

今回は Replication Pool の設定を以下のように行いました。

{
   "pools": {
      "A": {
         "servers": [
            // hosts of replicated pool, e.g.:
           "xxx.xxx.0.24:11211",
           "xxx.xxx.0.25:11211"
         ]
      }
   },
   "route": {
     "type": "PrefixPolicyRoute",
     "operation_policies": {
       "delete": "AllSyncRoute|Pool|A",
       "add": "AllSyncRoute|Pool|A",
       "get": "LatestRoute|Pool|A",
       "set": "AllSyncRoute|Pool|A"
     }
   }
 }

ざっくり…

  • pools でクラスタに所属するホストを設定
  • route で各メソッドごとの挙動を指定しています(上記の例では get は特定のノードから、それ以外は全てのノードに対して処理を行う指定です)

となります。

早速、mcrouter を起動してみます。

cd /opt/mcrouter/install/bin
./mcrouter -p 1919 -f /opt/mcrouter/conf/config.json

-f で設定ファイルを指定、-p で待機するポートを指定して起動すると…
以下のように出力されました。

root@e75ada9a6323:/opt/mcrouter/install/bin# ./mcrouter -p 1919 -f /opt/mcrouter/conf/config.json
I1214 15:43:10.932909  6245 main.cpp:521] ./mcrouter -p 1919 -f /opt/mcrouter/conf/config.json
I1214 15:43:10.933058  6245 main.cpp:638] mcrouter 1.0 startup (6245)
W1214 15:43:10.933117  6245 router.cpp:505] Error while checking spooldir (/var/spool/mcrouter): No such file or directory [2]
I1214 15:43:10.946666  6245 proxy.cpp:757] reconfigured 1 proxies with 2 clients and 1 pools (3c34b92c9496f2832622459f6d4a75d4)
I1214 15:43:10.948510  6245 server.cpp:143] Spawning AsyncMcServer

ありゃ、どうやら spooldir の設定が必要なようですので作成します。

mkdir /var/spool/mcrouter

気を取り直して起動しましょう。

root@e75ada9a6323:/opt/mcrouter/install/bin# ./mcrouter -p 1919 -f /opt/mcrouter/conf/config.json &
[1] 6271
root@e75ada9a6323:/opt/mcrouter/install/bin# I1214 15:45:59.649950  6271 main.cpp:521] ./mcrouter -p 1919 -f /opt/mcrouter/conf/config.json
I1214 15:45:59.650058  6271 main.cpp:638] mcrouter 1.0 startup (6271)
I1214 15:45:59.673478  6271 proxy.cpp:757] reconfigured 1 proxies with 2 clients and 1 pools (3c34b92c9496f2832622459f6d4a75d4)
I1214 15:45:59.674856  6271 server.cpp:143] Spawning AsyncMcServer

今度はちゃんと起動したようです。

動作確認

SET

以下のように mcrouter に対してデータを SET してみます。

root@e75ada9a6323:/opt/mcrouter/install/bin# telnet localhost 1919
Trying ::1...
Connected to localhost.
Escape character is '^]'.
set foo 0 100 4
hoge
I1214 16:04:54.596242  6277 ProxyDestination.cpp:223] server xxx.xxx.0.24:11211:TCP:ascii-1-0 up (1 of 2)
I1214 16:04:54.596276  6277 ProxyDestination.cpp:223] server xxx.xxx.0.25:11211:TCP:ascii-1-0 up (2 of 2)
STORED

上記のようにデータが格納されました。

GET

上記でセットしたデータを取得してみます。

root@e75ada9a6323:/opt/mcrouter/install/bin# echo -ne "get foorn" | nc 127.0.0.1 1919
VALUE foo 0 4
hoge
END

当たり前ですがデータの取得ができています。

node に障害

試しに一台の memcached ノードを停止してみると…以下のように mcrouter からログが出力されます。

root@e75ada9a6323:/opt/mcrouter/install/bin# I1214 16:10:39.149531  6277 ProxyDestination.cpp:241] server xxx.xxx.0.25:11211:TCP:ascii-1-0 down (0 of 2)

この状態からデータの取得を行うと以下のようにデータを取得することが出来ました。

root@e75ada9a6323:/opt/mcrouter/install/bin# echo -ne "get foorn" | nc 127.0.0.1 1919I1214 16:16:13.724607  6338 ProxyDestination.cpp:241] server xxx.xxx.0.24:11211:TCP:ascii-1-0 down (1 of 2)

VALUE foo 0 4
hoge
END

ちゃんとデータの同期が行われてるようです。

とりあえず…

今日はここまで。

ひとまず mcrouter をセットアップしてデータの登録と同期が行われているところまでは確認することが出来ました。
正直、CentOS でセットアップ出来ていないのがちょっと残念だったりしますが、引き続き mcrouter の動作についてドキュメントを読み進めながら整理していけたらなと思います。

上記の通り、セットアップできる環境が限られてしまいますが、従来から memcached にどうやって冗長性や可用性を持たせるかの解決策の一つとして参考にしたいと思います。また、mcrouter 自体が SPOF になってしまうのをどのように解決するか(mcrouter で巻き取れるのか他のミドルに頼るのか)についても引き続き追っていければと考えています。

おやすみなさい。

元記事はこちらです。
mcrouter で memcached へのアクセスを分散とレプリケーション Docker でちょろっと試す