2013-03-11 1 views
3

Я использую cake 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).')'; ?>

Я надеялся, что когда-то т он кэширует файл, как только первый человек получит доступ к нему, он будет радовать новый файл в кэше и подаст его на всех, однако, поскольку сотни людей попадают в него в секунду, похоже, что этот метод не работает для меня и что, возможно, я должен как-то кэшировать представление вида cron или, возможно, есть другой способ кэширования, который я не использую.

ответ

4

Похоже, у вас есть ответ более или менее разобрался (создать кэш автоматически, не запускается по запросу пользователя).

Для этого загляните в класс AppShell cake, book talks about it here. Затем вы можете связать это с заданием cron. Если вы создаете файл через Cache::write, торт должен знать, что это новый файл кеша и прозрачно его читать. Возможно, вы захотите оставить блок «if cache not found» на всякий случай, если ваш cronjob не удастся.

Корпуса & Задачи в торте - это забава и позволяет вам бесплатно освобождать приложение от использования модели запроса/ответа.

4

TLDR: Это не идеальный способ заставить пользователя сломать кэш для вас. Используйте хроновое задание или триггер при изменении данных.

Объяснение: «сотни просмотров в секунду» является проблемой. Когда он истекает, в то время, когда он пытается создать файл кеша, есть «сотни просмотров».

Первый человек попадает в него, он начинает создавать кэш, а тем временем еще 100 человек попадают в него, и он выглядит и еще не может найти файл кеша ... и т. Д.

Если вы можете управлять, попробуйте вручную создать кеш при обновлении какого-либо элемента или выполнить задание chron, которое создает новый кеш каждые X минут, в отличие от его создания для пользователя.

Торт имеет множество интересных триггеров, таких как afterSave(), которые вы можете использовать для запуска такого рода вещей. Если это не имеет смысла в вашем случае, то хрон-работа должна быть хорошей для вас.

+0

+1 за то, что вы обновили кеш, когда что-то обновлено (если возможно, с вашим приложением), поскольку это будет еще более эффективно, чем запуск cron каждые x минут/часов, когда это может даже не понадобиться. – Joseph

+0

Я бы согласился с обновлением 'afterSave()', однако это не совсем работает для этого конкретного экземпляра, потому что я обновляю базу данных с новой записью каждый раз, когда просматривается история. – bigmike7801

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 других людей также совершают вызов на поиск до завершения первого запроса.

Одним из вариантов решения:

кэшированное содержимое никогда не истекает.Настройка задачи хрон, которая перезаписывает кэш, вызвав другое действие, которое работает:

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

Чтобы перезаписать кэшированное содержимое.

Таким образом, 100s пользователей в секунду будет ВСЕГДА читать из кэша