ちょっと話題の記事

mcrouterでElastiCache(memcached)を分散レプリケーションする

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

先日9月15日、Facebookが開発した「mcrouter」がバージョン1.0として公開されました。mcrouterはmemcachedプロトコルをルーティングするソフトウェアで、クライアントとmemcachedサーバの間に立ってクエリをルーティングする仕組みになっています。このmcrouterを使うことで分散キャッシュシステムが構築出来ることになります。Facebookでは実際にインフラで導入しているそうです。

ElastiCache(memcached)では、Auto Discoveryを使ってノードをクラスタリングすることは出来ますが、キャッシュデータのレプリケーションは出来ません。しかしこのmcrouterのReplicated poolsを使うことで、ノード間でキャッシュデータを同期させることが出来ます。

そこでmcrouterを使って、分散配置したElastiCache(memcached)でキャッシュデータをレプリケーションしてみました!

準備

構成

AWS_Simple_Icons_2_2_light_edition_pptx

ElastiCacheの構築

memcachedエンジンで、2つのノードを構築しました。特に変わった設定はしていません。

ElastiCache_Management_Console

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に影響を与えることなく導入が可能なので、今後需要が高まって行くのでは無いでしょうか。