handlersocket plugin や mycached を使えば memcached は不要か、それとも使うべきケースがあるか。考察せよ [10点] kazuho (Kazuho Oku)

http://twitter.com/kazuho/status/21477219149

考えて答えてみる。

HandlerSocketやmycachedを利用し、MySQLへの接続数が数万単位で行えるようになったり、より多くのクエリ数が発行できるようになっても、memcachedは不要ではないし、使うべきケースもあります。

memcachedは単なるKVSではなく、ExpiresとLRUがついたキャッシュサーバです。キャッシュオブジェクトには期限を付ける事ができ、期限が過ぎたキャッシュは無効にされ、またアクセスがされていない不要になったオブジェクトは削除され、空いたスペースは新しいキャッシュオブジェクトのために再活用されます。これらが自動で行われるのがmemcachedです。そしてこの特徴をもっとも生かす使い方がこそが、汎用的に利用できる一時的なデータ保存、キャッシュだと考えます。

memcachedをWebアプリケーションで利用する際に、よくあるパターンとしてORM(ORマッパー)にmemcachedを組み込み、PRIMARY KEYなどの検索結果をそのままmemcachedに格納することがあります。しかし、この使い方ではデータソース(データベース)の出力結果をキャッシュするだけです。memcachedにはもっと多くの種類のデータ、なんらかの処理結果や処理途中のデータも期限をつけて格納することができます。

memcachedが有効であるパターンとして以下が考えられます。

  • データベース以外のデータソース。外部APIなど
  • テキストデータの変換、データ集計など比較的重い処理の結果
  • 連続アクセスblockなどの軽いセッション処理

外部APIのデータでmemcachedを利用するケースとしてはソーシャルアプリケーションが上げられます。ソーシャルアプリケーションにおいてはOpenSocial APIに問い合わせを行いユーザデータを取得することがありますが、その際ユーザのアクセスがあるたびにAPIへ問い合わせを行っていては、レスポンス速度に影響でますし、サービスをスケールさせていくことができません。そこでOpenSocial APIの問い合わせ結果をソーシャルアプリケーションを提供するサーバ側に置き、2度目以降はそれを参照することが必須となります。 mixiアプリではOpenSocial APIで取得したユーザデータの保存は24時間までとされており、24時間以内に更新または削除が必要となります。データベース等にOpenSocial APIの問い合わせ結果を入れてしまうと、別途cronで削除または更新することになりますが(この削除スクリプトの設計もデータが多くなると難しい)、memcachedであれば、有効期限を24時間としてキャッシュするだけで、(memcachedの容量が足りていれば)有効期限までデータを保持し、自動的に有効期限が切れればキャッシュの参照ができなくなります。削除されたデータは次回ユーザのアクセスがあった際に再度OpenSocial APIに問い合わせればサービスに影響はでません。

また、有効期限がきたら削除されることを期待した利用方法として、大量のデータからの一部のデータを抜き出すときや、最新情報のキャッシュがなどがあげられます。twitterのフォロワーのような多くのユーザリストから、ランダムに数件を表示したいと言ったときに、毎回すべてのフォロワーのリストをデータベース上でランダムに並べ替え、一部だけ抜き出して利用するのはデータベースサーバの負荷が大きくなることが予想できます。そこでフォロワーのリストを一度そのままmemcachedに入れ事も考えられますが、全部で数万となる可能性があるリストが毎回アプリケーションサーバとmemcachedサーバの間で転送されるのはそれはそれで負担が大きくなります。そこで表示する全件よりすくなく、件数よりも若干多い表示用リストを生成し、それを有効期限をつけてmemcachedに入れることにします。表示するときはこの表示用リストからランダムに表示します。これだけだとすべてからフォロワーからランダムに表示とは言えませんが、表示用リストは有効期限があるため、指定した時間後にmemcached上の表示用リストが無効になり、再度全件からリストを作り直すことになるので長い時間として見れば、ランダムが実現できます。この方法であれば無駄なデータのやり取りは少なく負荷も増えないと思われます。

すこし以前から言われていることですが、ORMをMVCモデルにおけるModelそのものとして扱うことで、本来Modelで扱うビジネスロジックをControllerに書いてしまい、Controllerのロジックが増大し、結果的にメンテナンスがしにくい、拡張が難しいコードが生まれてしまいがちです。

mvc.png

この状態でmemcachedをORMに組み込んでしまうことで、より汎用的な使い方ができないままであり、無理にORMの外でもmemcachedを利用しようとすると、余計にControllerの厚さが増していってしまう。その対策として、Modelを見直しを行い、ORM、DBI、Web API、他のKVS、そしてmemcachedなどマルチソースでビジネスロジックを記すレイヤーとしての位置づけとすることを考えてみたい。多くの情報を扱う今、こちらの考え方が自然に設計ができると考えます。

mvc2.png

多くのアプリケーションでは、データベースの入出力が処理の大部分を占めていると思われますが、Webアプリケーションで多様なデータを扱うようになってくる今、memcachedをより汎用的に使うことでまだまだ高速なレスポンスが実現できるはずです。

かなり脱線しましたが、HandlerSocketやmycachedでMySQLの処理が高速になったとしても、memcachedが無用になるわけではなく、高速で汎用的なキャッシュとしてWebアプリケーションのさまざまな場所で活躍できると考えています。

このブログ記事について

このページは、Masahiro Naganoが2010年8月20日 10:55に書いたブログ記事です。

ひとつ前のブログ記事は「技術評論社のgihyo.jpにてmemcachedの(再)連載をします」です。

次のブログ記事は「[gihyo.jp連載] 第二回 memcachedのセキュリティと脆弱性」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。

ウェブページ

OpenID対応しています OpenIDについて
Powered by Movable Type 4.27-ja