Road To Nowhere

主にWebまわりのエンジニア的なお仕事に関するようなことのあれこれ。

PHPでクラスタ構成のmemcachedサーバを利用するときに気をつけること

ちょっとはまったけど解決してスッキリしたので共有。
今回発覚したトラブルは、
セットしたはずの値を取得できない
というもの。

環境はこちら。

memcachedクラスタ構成っていうのは

addServer('hostA', 11211);
addServer('hostB', 11211);
addServer('hostC', 11211);

こういう風に複数回addServerしているようなケース。

あまり珍しい環境ではないよね。中規模以上のWebサイトではよくある構成じゃないかな。これに加えてうちの特殊なところは、複数フレームワークが混在していてMemcachedオブジェクトの作成やaddServerしている箇所が複数あるところ。これもトラブルの元だった。
以下2点解決して正しく動作するようになったので、気をつけることとしてメモしておく。

その1、クラスタ構成は必ず統一すること!

これは複数フレームワークの混在が招いたことだけど、それぞれのアプリケーションでaddServerしているサーバに差分があった。当然と言えば当然。だけど、間違って理解していた部分があったので説明しておく。

アプリX

addServer('hostA', 11211);
addServer('hostB', 11211);

アプリY

addServer('hostA', 11211);
addServer('hostB', 11211);
addServer('hostC', 11211);

こういう状況のとき、アプリXでセットした値はhostA、hostBのいずれかに保存される。
このときアプリYではhostA、hostBも構成に入っているのでアプリXでセットした値は参照できるような気がしないかな?
答えはNO。クラスタ構成の場合、キーによって参照先(あるいは保存先)のサーバが分散されるので、hostAに存在する値なのにクラスタ構成が異なると、アプリYではhostBを参照しにいってしまって、結果取得できないということが起こる。
たまたま値が存在するサーバを参照する場合もあるけど、ヒットしたりしなかったりはこちらの期待している動作ではない。

さて、これで解決かと思ったが。

その2、memcached.hash_strategyを統一すること!

上記の問題を解決したところヒット率は多少あがったけれども、まだ取得できるはずの値が取得できないことがあった。
しばし調査の結果、アプリケーションサーバPHP動作環境に差分があったことが発覚。
あるサーバはmemcached.hash_strategyconsistentなのにあるサーバはstandardだった。
これはキーを元にどのサーバに保存するかのマッピングの方法を指定するもので、これが違うと同じキーでも当然参照先(あるいは保存先)のサーバが変わってくると。

詳しくはこちら。あまり詳しくないけど。
http://php.net/manual/ja/memcache.ini.php#ini.memcache.hash-strategy
クラスタ構成変更時に再マッピングの必要のないconsistentが正解でしょう。

php -i | grep memcache

これで確認できるのやってみるとよいかも。

まとめ

memcachedは導入も運用も簡単なので今まで苦労したことがなかったけど、今回思わぬ落とし穴にはまってしまったなという感じ。まぁでも勉強不足のたまものだな。反省。