2013-03-11 52 views
3

我使用的是蛋糕2.1.3,目前有一個網頁每秒獲得數百個視圖,所以我已經使用了單詞緩存以更好地處理負載。問題是,一旦緩存過期,我的服務器資源以及數百個mysql連接就會出現峯值。CakePHP:爲什麼我的緩存文件在到期時會導致巨大的峯值?

我想知道如果我這樣做是錯誤的方式,如果我應該運行一個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).')'; ?>

我希望,一旦ŧ他緩存文件到期,只要第一個人訪問它,它就會創建一個新的緩存文件併爲每個人提供服務,但是因爲每秒有數百人在觸碰它,所以似乎這種方法不適合我也許我應該以某種方式緩存視圖視圖,或者也許有一種不同的方式來緩存,我不是在utelizing。

回答

4

讀這聽起來像你有答案或多或少想通了(自動創建緩存,而不是由用戶請求觸發)。

要做到這一點,看看蛋糕的AppShell類,book talks about it here。然後,您可以將其鏈接到cron作業。如果通過Cache::write創建文件,cake應該知道它是一個新的緩存文件並透明地讀取它。您可能希望將「if cache not found」塊留在那裏,以防cronjob失敗。

殼&蛋糕中的任務很有趣,並允許您將應用程序從專用的請求/響應模式中解放出來。

4

TLDR:強迫用戶爲您分配緩存並不理想。數據更改時使用時間作業或觸發器。

說明: 「每秒數百意見」的問題。當它到期時,在嘗試創建緩存文件的時候會有「數百個視圖」。

第一個人點擊它,它開始創建緩存,同時,有另外100多個人打它,它看起來,並且還找不到緩存文件等等。

如果你能管理,儘量手動創建緩存時的項目(S)被更新,或運行創建一個新的緩存,而不是讓它爲用戶創建每隔X分鐘代下工作。

蛋糕有很多很酷的觸發器,如afterSave(),你可以用它來觸發這種事情。如果這對你的情況沒有任何意義,那麼你的工作應該沒問題。

+0

+1用於在更新某些內容時重新構建緩存(如果可能,使用您的應用程序),因爲如果甚至沒有必要,這會比每隔x分鐘/小時運行一次cron更有效。 – Joseph 2013-03-12 02:00:21

+0

我通常會同意'afterSave()'的更新,但是這對於這個特殊的實例並不適用,因爲我每次查看故事時都會用新記錄更新數據庫。 – bigmike7801 2013-03-12 18:58:10

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, 
     )); 

可以說,它需要500毫秒。

您每秒獲得100次點擊,因此當緩存清除第一個請求時,會發出查找呼叫,然後另外50個人也會在第一個請求完成之前發出查找呼叫。

一種替代方案:

緩存的內容永不過期。設置一個cron任務,通過調用其他操作來覆蓋緩存:

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

覆蓋緩存的內容。

這種方式,每秒用戶的100S將總是從緩存

相關問題