mcrouterでElastiCache(memcached)を分散レプリケーションする
はじめに
先日9月15日、Facebookが開発した「mcrouter」がバージョン1.0として公開されました。mcrouterはmemcachedプロトコルをルーティングするソフトウェアで、クライアントとmemcachedサーバの間に立ってクエリをルーティングする仕組みになっています。このmcrouterを使うことで分散キャッシュシステムが構築出来ることになります。Facebookでは実際にインフラで導入しているそうです。
ElastiCache(memcached)では、Auto Discoveryを使ってノードをクラスタリングすることは出来ますが、キャッシュデータのレプリケーションは出来ません。しかしこのmcrouterのReplicated poolsを使うことで、ノード間でキャッシュデータを同期させることが出来ます。
そこでmcrouterを使って、分散配置したElastiCache(memcached)でキャッシュデータをレプリケーションしてみました!
準備
構成
ElastiCacheの構築
memcachedエンジンで、2つのノードを構築しました。特に変わった設定はしていません。
mcrouterサーバの構築
mcrouterのインストールは以下のものが必要になります。
これらをそれぞれパッケージとしてインストールするのはかなり大変です。実際にAmazon Linuxで試してみたのですが、不足パッケージが多過ぎて断念しました。しかしUbuntu用には自動インストールスクリプトが用意されていますので簡単に構築することが出来ます。このため今回はUbuntuを使いました。
EC2をUbuntuでLaunchします。AMIはubuntu-trusty-14.04-amd64-server-20140607.1を使いました。Launch後、ubuntuユーザでログインし、とりあえずパッケージを最新にしておきます。
$ sudo apt-get update $ sudo apt-get upgrade
mcrouterはgitで配布されていますので、gitをインストールします。
$ sudo apt-get install git
git cloneコマンドで、mcrouterのリポジトリを取得します。
$ git clone https://github.com/facebook/mcrouter.git
自動インストールスクリプトを使ってmcrouterをbuildします。なおコンパイル時にメモリをがっつり使う為、t2.microだとCannot allocate memoryが出てコンパイルが進まなくなりました。t2.smallだと大丈夫でした。
$ sudo ./mcrouter/mcrouter/scripts/install_ubuntu_14.04.sh /home/$USER/mcrouter-install/ -j4
これでmcrouterのインストールは完了です。
次にmcrouter用の設定ファイルを作成します。"elasticache"というプールを作り、そこにElastiCacheの2つのノードを登録しています。またrouteの設定でelasticacheプールを使い、setとdeleteはプール内の全ノードに対して行い、getのみ特定のノードから行うように設定しています。
# vi ~/mcr.conf { "pools": { "elasticache": { "servers": [ "mcroutertest.16bbhn.0001.apne1.cache.amazonaws.com:11211", "mcroutertest.16bbhn.0002.apne1.cache.amazonaws.com:11211" ] } }, "route": { "type": "PrefixPolicyRoute", "default_policy": "PoolRoute|elasticache", "operation_policies": { "delete": "AllSyncRoute|Pool|elasticache", "get": "LatestRoute|Pool|elasticache", "set": "AllSyncRoute|Pool|elasticache" } } }
さてmcrouterを起動...の前に、/var/spool/mcrouterというフォルダを作ります。手作業で作らないとプロセス起動時にエラーが発生しました。
$ sudo mkdir /var/spool/mcrouter
では、以下のコマンドにてmcrouterを起動します。
$ sudo ~/mcrouter-install/install/bin/mcrouter -p 5000 -f ~/mcr.conf I0926 04:49:39.691131 1448 main.cpp:625] mcrouter 1.0 startup (1448) I0926 04:49:39.702901 1448 proxy.cpp:956] reconfigured 1 proxies with 2 clients and 1 pools (a4860fd115be28ffdeff57d6ec5cdc78) I0926 04:49:39.703214 1448 server.cpp:141] Spawning AsyncMcServer
はい、起動しました!
試してみる
set/get
では実際に試してみましょう。まずmcrouterに接続し、1stというkeyをsetしてみます。
$ telnet localhost 5000 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. set 1st 0 0 8 1st_set STORED
そのままgetすると、ちゃんと値が取得できます。
get 1st VALUE 1st 0 8 1st_set END
1台目のElastiCacheノードに接続しgetしてみると、ちゃんと値が取得できます。
$ telnet mcroutertest.16bbhn.0001.apne1.cache.amazonaws.com 11211 Trying 172.31.8.10... Connected to mcroutertest.16bbhn.0001.apne1.cache.amazonaws.com. Escape character is '^]'. get 1st VALUE 1st 0 8 1st_set END
次に2台目のElastiCacheノードに接続しgetしてみると、そちらでもちゃんと値が取得できます。
$ telnet mcroutertest.16bbhn.0002.apne1.cache.amazonaws.com 11211 Trying 172.31.15.251... Connected to mcroutertest.16bbhn.0002.apne1.cache.amazonaws.com. Escape character is '^]'. get 1st VALUE 1st 0 8 1st_set END
以上から、複数ノードに同期してsetが行われていることが分かります。
delete
mcrouterに接続し、先ほどsetした1stというkeyをdeleteしてみます。
$ telnet localhost 5000 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. delete 1st DELETED
そのままgetしても、deleteされているので取得出来ません。
get 1st END
1台目のElastiCacheノードに接続しgetしてみると、ちゃんと値がdeleteされていて取得出来ません。
$ telnet mcroutertest.16bbhn.0001.apne1.cache.amazonaws.com 11211 Trying 172.31.8.10... Connected to mcroutertest.16bbhn.0001.apne1.cache.amazonaws.com. Escape character is '^]'. get 1st END
次に2台目のElastiCacheノードに接続しgetしてみると、そちらでも値がdeleteされていて取得出来ません。
$ telnet mcroutertest.16bbhn.0002.apne1.cache.amazonaws.com 11211 Trying 172.31.15.251... Connected to mcroutertest.16bbhn.0002.apne1.cache.amazonaws.com. Escape character is '^]'. get 1st END
以上から、deleteもちゃんと複数ノードで同期して行われていることが分かります。
まとめ
mcrouterサーバも分散配置してInternal ELBでバランシングすると、更に可用性が高まるかと思います。既存のmemcachedに影響を与えることなく導入が可能なので、今後需要が高まって行くのでは無いでしょうか。