クライアントからmemcachedを利用する際の、ベストプラクティスは以前書いているので、その前段階でmemcachedを含めたWebアプリケーションのアーキテクチャ(と一部クライアントの話)について今の個人的な考えをまとめてみます。Kyoto Tycoonを使ったキャッシュサーバでも基本は同じだと思います
1) 使わない
memcachedをアプリケーションに組み込むことで、プログラムがどうしても複雑になりがちです。データの削除や更新の際にキャッシュの更新を忘れると多くの問題が発生します。例えばユーザがニックネームやプロフィール写真を更新したのに画面上変わらないなどの現象が起こると、ユーザに対して不快な思いをさせてしまうでしょう。またデータベースが非同期のレプリケーションを行っている場合、masterに対してデータの変更をかけ、更新が反映される前にslaveから読み込んでしまい、キャッシュに保存してしまうと問題はさらに大きくなります。対応策としてexpires時間を短くしていることが散見されますが、本末転倒な気がします。
現代的なハードウェア、最新のMySQLを利用し、適切なスキーマ設計・SQLであればMySQLは数百qps〜数千qpsのパフォーマンスを発揮します。もしこの数値でも足りないということであれば”“ピンポイント”“でmemcachedを導入することをお勧めします。よくあるORMのmemcached連携機能は使ってはいけません。
2) 消えては困るキャッシュを置かない
memcachedは揮発性のKVSで、再起動するとすべてのデータが失われるから消えては困るキャッシュを置いては行けない。というのはよく言われていることかもしれませんが、実は本質ではありません。memcachedの単体再起動はあまりすることではありませんし。
アプリケーションを効率よく運用していくために、スケールアウト(台数追加)、スケールアップ(性能の高いサーバに入れ替え)、スケールイン(台数削減)、スケールダウンなどサーバの入れ替えはいつでも行えるようにしてして置くことが必要です。memcachedのキャッシュの分散はクライアントのアルゴリズムにもよりますが、サーバの追加削除によってキャッシュミスが少なからず起こりえます。
消えては困るキャッシュの代表がセッションだと思います。このようなデータは別の永続化できるデータベースに(も)格納したり、Cache::Memcached::IronPlateのキャッシュ複製機能を利用し複数のmemcachedに格納するなどの対応策が考えられます。
3) リスクヘッジのためにmemcachedサーバはスケールアウトを行う
メモリの単価が下がったことで1台のサーバで16GB〜数十GBのメモリを積むことは珍しくなくなりました。memcachedも一つのインスタンスで数十GBをメモリを確保して使うことができます。しかし、スケールアップすることで1台のmemcachedサーバに障害があった場合、アクセスできなくなるキャッシュも膨大になるのでサービスへの影響が大きくなりがちです。適切なスケールアウトも行いましょう。
スケールアウトを行うことでサーバ群の障害発生可能性は上がります。Consistent-Hashingを利用したmemcachedクライアントライブラリでは、障害を検知して別のサーバへアクセスをし直すrehashの機能を持たないものがあります。その場合特定のキーだけキャッシュに保存できないので、サービスへの影響がでてくる可能性があります。そのようなキャッシュでもCache::Memcached::IronPlateのキャッシュ分散・複製機能が活用できるでしょう。メモリは余裕あるので複製しても問題はないはずです
様々なミドルウェアが出てくる中で、memcachedだけが唯一の選択肢ではなくなってきていると思います。しかし雨後のタケノコのようにでてくる多くのミドルウェアを同時に運用するのはなかなか骨の折れる作業です。冷静な技術の判断と適切なサイジングが重要なこのごろです。