PHPでクラスタ構成のmemcachedサーバを利用するときに気をつけること
ちょっとはまったけど解決してスッキリしたので共有。
今回発覚したトラブルは、
セットしたはずの値を取得できない
というもの。
環境はこちら。
- pecl Memcachedを使用
- memcachedサーバ複数台でクラスタ構成
- アプリケーションサーバ(PHPの動作環境)も複数台
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_strategyがconsistentなのにあるサーバはstandardだった。
これはキーを元にどのサーバに保存するかのマッピングの方法を指定するもので、これが違うと同じキーでも当然参照先(あるいは保存先)のサーバが変わってくると。
詳しくはこちら。あまり詳しくないけど。
http://php.net/manual/ja/memcache.ini.php#ini.memcache.hash-strategy
クラスタ構成変更時に再マッピングの必要のないconsistentが正解でしょう。
php -i | grep memcache
これで確認できるのやってみるとよいかも。
まとめ
memcachedは導入も運用も簡単なので今まで苦労したことがなかったけど、今回思わぬ落とし穴にはまってしまったなという感じ。まぁでも勉強不足のたまものだな。反省。