3

私はCake2.1.3を使用していて、現在1秒あたり数百回のビューを取得しているページがあるため、負荷をより適切に処理するためにキャッシュを利用しました。問題は、キャッシュの有効期限が切れると、サーバーリソースと数百のmysql接続が急増することです。

私はこれを間違った方法で行っているのか、現在の方法ではなくcronを実行してページをキャッシュする必要があるのか​​、それとも私が考えていない別の手法があるのか​​疑問に思っています。

これが私のコントローラーでの私の関数の様子です:

public function index() {
    $this->layout = 'ajax';

    if (isset($this->params['url']['callback'])) {
        $callback =  $this->params['url']['callback'];
    }else{
        $callback = 'callback';
    }
    $this->set('callback',$callback);

    $today = date("Y-m-d");
    $end_date = strtotime ('+1 day' , strtotime($today)) ;        
    $end_date = date ( 'Y-m-d' , $end_date);

    $start_date = strtotime ('-1 day' , strtotime($today)) ;
    $start_date = date ( 'Y-m-d' , $start_date);

    $total = Cache::read('popular_stories', 'short');
    if (!$total) {
        $total = $this->TrackStoryView->find('all', array(
           'fields' => array('COUNT(story_id) AS theCount', 'headline', 'url'), 
           'conditions' => array('date BETWEEN ? AND ?' => array($start_date,$end_date)),
           'group' => 'story_id',
           'order' => array('theCount DESC'),
           'limit' => 20,
        ));
        Cache::write('popular_stories', $total, 'short');
    }

    $this->set('story', $total);    
}

bootstrap.phpファイルでのキャッシュ構成は次のようになります。

Cache::config('short', array(
    'engine' => 'File',
    'duration' => '+60 minutes',
    'path' => CACHE,
    'prefix' => 'cake_short_'
));

これは私のビューファイルにあるものです:

<?php echo $callback . '('.json_encode($story).')'; ?>

キャッシュされたファイルの有効期限が切れると、最初の人がアクセスするとすぐに、新しいキャッシュされたファイルが作成され、すべての人に提供されることを期待していましたが、毎秒何百人もの人がファイルにアクセスしているため、この方法はそうではないようです。私のために働いていません、そして多分私は代わりに何らかの方法でビュービューをcronにキャッシュするべきです、あるいは多分私が利用していないキャッシュする別の方法があります。

4

3 に答える 3

4

TLDR:ユーザーにキャッシュを壊してもらうのは理想的ではありません。データ変更時にcronジョブまたはトリガーを使用します。

説明: 「1秒あたり数百ビュー」が問題です。有効期限が切れると、キャッシュファイルを作成しようとしている間に「数百のビュー」が発生します。

最初の人がそれをヒットし、それがキャッシュの作成を開始し、その間に、さらに100人以上の人がそれをヒットし、見た目はまだキャッシュファイルを見つけることができません...など。

管理できる場合は、アイテムが更新されたときに手動でキャッシュを作成するか、ユーザー用に作成するのではなく、X分ごとに新しいキャッシュを作成するcronジョブを実行してみてください。

Cakeには、afterSave()この種のものをトリガーするために使用できるようなクールなトリガーがたくさんあります。ただし、それがあなたのケースで意味をなさない場合は、cronジョブで問題ないはずです。

于 2013-03-11T15:07:58.560 に答える
4

答えは多かれ少なかれ理解されているようです(ユーザーの要求によってトリガーされるのではなく、キャッシュを自動的に作成します)。

これを行うには、ケーキのAppShellクラスを調べて、ブックトークでそれについて説明します。次に、これをcronジョブにリンクできます。を介してファイルを作成する場合Cache::write、cakeはそれが新しいキャッシュファイルであることを認識し、透過的に読み取る必要があります。cronジョブが失敗した場合に備えて、「キャッシュが見つからない場合」ブロックをそのままにしておくことをお勧めします。

ケーキのシェルとタスクは楽しく、アプリケーションが要求/応答モデルを排他的に使用することから解放されます。

于 2013-03-11T15:18:12.877 に答える
2

答えは、このクエリにかかる時間を計算することだと思います。

$total = $this->TrackStoryView->find('all', array(
           'fields' => array('COUNT(story_id) AS theCount', 'headline', 'url'), 
           'conditions' => array('date BETWEEN ? AND ?' => array($start_date,$end_date)),
           'group' => 'story_id',
           'order' => array('theCount DESC'),
           'limit' => 20,
        ));

500msかかるとしましょう。

1秒間に100ヒットを取得しているため、キャッシュがクリアされると、最初のリクエストが検索呼び出しを行い、最初のリクエストが完了する前に他の50人も検索呼び出しを行います。

1つの代替ソリューション:

キャッシュされたコンテンツが期限切れにならないようにします。実行する別のアクションを呼び出して、キャッシュを上書きするcronタスクを設定します。

Cache::write('popular_stories', $total, 'short');

キャッシュされたコンテンツを上書きします。

このように、1秒あたり数百人のユーザーが常にキャッシュから読み取ります

于 2013-03-11T15:10:16.680 に答える