世界中の共有動画を横断検索。youku.com,youtube,tudou.com,Dailymotionに対応。・・・そんなサービスの開発者ブログ。

みんなの動画サーチ

個人メニュー
最近見た動画

サービス:みんなの動画サーチ   利用できる動画共有サイト : youku.com , youtube , tudou.com , Dailymotion

Ads by Google

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。
--------(--)

みんなの動画サーチを実例としたPHPでの開発における負荷対策について 第8回 出力キャッシュの利用

 みんなの動画サーチを実例としたPHPでの開発における負荷対策について 第8回  では負荷対策には必須の技術、出力キャッシュの利用についてです。

 以前インデックスぺージで秒間あたりの表示数が4倍になったと書いたことがありますが、それは後で述べるAPC利用もさることながら、この出力キャッシュを利用する処理を追加したからです。それほどに効きます。負荷対策には必須の手法と言えます。
 ではさっそくはじめます。

出力キャッシュはこんなに効く

 ではどれくらい効果があるのかをまずご覧ください。こちらはABを使って開発環境で出力キャッシュありの場合となしの場合を比較した結果です。
 なお、利用したコマンドは「ab -n 100 -c 10 http://192.168.0.2/movie-search/www/」です。

インデックスページ

キャッシュあり
Requests per second:    15.77 [#/sec] (mean)

キャッシュなし
Requests per second:    3.91 [#/sec] (mean)

 ごらんのとおり、キャッシュなしの場合と比べ、約4倍のパフォーマンスとなっています。インデックスはその性格上大量の情報を載せるためデータベースへの接続が多く(4回)、他のページよりもキャッシュの効果が高い傾向があります。

 他のページは約2倍のパフォーマンスとなっています。

タグページ

キャッシュあり
Requests per second:    15.42 [#/sec] (mean)

キャッシュなし
Requests per second:    7.25 [#/sec] (mean)
カテゴリページ
キャッシュあり
Requests per second:    14.19 [#/sec] (mean)

キャッシュなし
Requests per second:    7.30 [#/sec] (mean)

動画表示ページ

キャッシュあり
Requests per second:    14.45 [#/sec] (mean)

キャッシュなし
Requests per second:    8.22 [#/sec] (mean)

キャッシュとはどのような処理か?

 「処理結果を一度ファイルに保存しておく」これが出力キャッシュです。作成されたキャッシュがある場合はデータベースへの接続やレンダリングエンジンの利用がないため、はるかに高速かつ低負荷で表示することができます。高い負荷がかかるランキングシステムなどには必ずと言っていいほど使われているようです。(時間は5分おきであったり1時間おきであったりと千差万別です)
 単純に表示が速くなるほかに、CPUやデータベースサーバへの負荷が削減できる点もメリットです。そのため、キャッシュを導入すると、他のキャッシュを利用していないページにも効果が表れます。

 キャッシュが作られていない場合は重いのですが、これは仕方ないと割り切るか、バックグラウンドであらかじめキャッシュファイルを作成しておくと良いです。

 ちなみにみんなの動画サーチでは割り切っています。キャッシュなしでも致命的に遅いわけではない、バックグラウンドでキャッシュファイルを作るにはページが多すぎる、という理由によります。 

キャッシュを利用するコードの実例

 例によってみんなの動画サーチからコードをひっぱってきます。
 これはトップページ表示画面のビジネスロジック部分を抜き出したものです。indexクラスがメインの処理、cache()とgetcacheAction()がキャッシュを利用するための関数です。
 getcacheAction()をindex::execute()の外に出しているのは、indexクラス以外にtagクラスやcategoryクラスなどほかの処理でも同じことをやるためです。

//$Timeは1あたり12時間。キャッシュがないか時間切れならFalseが返る。
function cache($Filename,$Time=2){
        if(file_exists($Filename)){
                if(time() - filemtime($Filename) <= 60*30*24*$Time){
                        return file_get_contents($Filename);
                }
        }
        return false;
}

function getcacheAction($Action , $Filename , $LifeTime){ 
        $Html = cache( $Filename , $LifeTime);
        if(empty($Html)){ //HTMLファイルが返ったことを確認してから処理を省く
                $Action->main();
                $Renderer = new Renderer_Smarty;
                $Renderer->setConfig(DEFMODULE);
                $Html = $Renderer->fetch($Action->tpl , $Action->Vals);
                file_put_contents($Filename , $Html);
        }
        return $Html;
}

class index extends Action
{
    function Execute ()
    {
        //
        //ページングがあるからそれも考慮。
                $start = isset($this->GPVal["start"]) ? $this->GPVal["start"] : 1 ;
                $cachefile = BASE_DIR.'cache/index/'.stripslashes_deep($start).".cash";

                exit(getcacheAction($this , $cachefile , 0.1));

        
    }

    function main()
    {
         //省略するが、ここにはデータベースへの接続などのビジネスロジックが存在する。
                $this->sendVal("TagCloud" , $TagCloud); //レンダリングエンジンに渡したい変数を指定している
                $this->designateTpl("index.tpl"); //利用するテンプレートを指定している
    }
}

 ポイントは空白ではないHTMLデータが返ったことを確認してから処理を省く仕様になっている点です。キャッシュファイルがあるかどうかだけで処理をはぶく仕様にすると、とてもタイミングが悪い場合に表示がされません。たとえばこういう処理です。

if(file_exists("index.cash")){ //ここでキャッシュ判定した後で
        //こちらの処理に移る前に不運にしてキャッシュファイルの内容が消えてしまった場合
        print file_get_contents("index.cash"); //ここでは空白が表示される(=期待した表示はされない)
        return;
}
$Html = makeHtml();
file_put_contents("index.cash",$Html); //ここで内部的にいったん内容を消してから作成している。
print $Html;

 file_get_contents()やfile_put_contents()はファイルロックを行なわないので、非常に運が悪いとキャッシュ読み込みとキャッシュ再作成のタイミングが重なり、"index.cash"の内容が消去された後で読み込んでしまう可能性があります。マルチタスクであるWEBは注意しないといけない点です。(こんな不運はめったにないのもたしかです――ですがだからこそ気がつきづらく困りやすいです)

 二重ロックをかけるなどして排他処理をきっちかけつつ上記のような処理を行えばこのような不運は起こらないわけですが、いちいち二重ロックをかけるのはそれはそれで負荷がかかって嫌なので、今回は選択しませんでした。

外部からデータを取得する際は必須

 WEB APIやRSSなど、外部からデータを取得する場合は、このキャッシュの利用は必須です。
 表示を早くする、負荷を軽減するという目的もありますが、なによりリクエストを送る相手へ負荷をかけすぎないためです。迷惑ですし、また、なんらかのペナルティがかけられる可能性もあります。

 たとえば、ある大規模サービスには過去このキャッシュが効いていないバグがあり、膨大なリクエストを送った結果としてWEB API提供元からアクセスを遮断される羽目になったことがあるそうです。(そのサービスの開発者ブログで報告されていました)

 影響範囲は多大なものがありますから、必ずキャッシュを利用するようにします。
 もちろんみんなの動画サーチでも外部データを利用する場合必ずキャッシュを利用しています。

キャッシュ利用のデメリット

 とても効果が高いキャッシュですが、デメリットもあります。

  1. キャッシュファイルがたまりすぎると負荷が増す・・・1ディレクトリに対して10000ファイルが許容範囲です。ディレクトリ設計を適切に行う必要があります。
  2. ページングを行う際にバグが発生しやすい・・・キャッシュファイル名を工夫しないと1ページ目も2ページ目も同じ内容が表示されてしまいます。
  3. 更新があっても反映が遅くなる・・・キャッシュが生きているかぎりそちらが表示されてしまいます。これは対処困難です。
  4. 効果がでるのは2度目以降・・・先にも述べましたが、一回目はそのまま負荷がかかります

 3番目と4番目が特に問題で、この理由により更新頻度が高い画面や、また更新がリアルタイムで行われる画面にはキャッシュは向きません。みんなの動画サーチでは「最近見た動画」がこれにあたります。
 また、利用頻度が低く、ライフタイムの時間当たり1回しか見られないような場合もキャッシュはあまり意味をなしません。

 そのためキャッシュを使えば使うほどいいというわけではなく、どこで利用するかはよく検討しないといけません。(できれば設計時に)

tag : php 負荷対策 みんなの動画サーチ

2008-05-08(Thu)

 みんなの動画サーチ 現在の人気動画

RSSフィード
最近の記事
月別アーカイブ
カテゴリー
逆アクセスランキング
プロフィール

Author:ナカタツ
 共有動画サーチの開発をやっているフリーランサーです。プログラム歴は趣味で使っていた頃も合わせるとちょうど今年で10年目。最近はPHPばかり使ってます。
 私に興味を持ってくださる方はお気軽にご連絡ください。Skypeでお話できる人歓迎。メールフォームはこちら

カレンダー
10 | 2009/11 | 12
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 - - - - -

みんなの動画サーチへ戻る

カテゴリ:芸能・テレビ | 音楽 | アニメ | おもしろ | 神・衝撃 | ゲーム | 動物 | スポーツ | 時事ニュース | 自然・歴史 | 車・バイク | セクシー


アクセス解析 アクセスランキング
  • seo

Powered by FC2 Blog

FC2Ad

FC2ブログ

Copyright © みんなの動画サーチ開発者ブログ All Rights Reserved.