CakePHP:为什么我的缓存文件在到期时会导致巨大的峰值?

时间:2013-03-11 15:05:29

标签: cakephp caching cron cakephp-2.1

我正在使用cake 2.1.3并且目前有一个页面每秒可以获得数百个视图,所以我有一个utelized缓存来更好地处理负载。问题是,一旦缓存过期,我的服务器资源以及数百个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配置:

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

这是我的视图文件中的内容:

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

我希望一旦缓存的文件过期,只要第一个人访问它,它就会创建一个新的缓存文件并为每个人提供服务,但是因为每秒有数百人在点击它,所以看起来像这个方法对我来说不起作用,也许我应该以某种方式缓存视图视图cron,或者可能有一种不同的方式来缓存我不是utelizing。

3 个答案:

答案 0 :(得分:4)

TLDR:强制用户为您打破缓存并不理想。在数据更改时使用计时作业或触发器。

<强>说明: “每秒数百次观看”是问题所在。当它到期时,在尝试创建缓存文件期间会有“数百个视图”。

第一个人点击它,它开始创建缓存,同时,另外一百多人点击它,它看起来,但还不能找到缓存文件......等等。

如果您可以管理,请尝试在更新项目时手动创建缓存,或者运行每隔X分钟创建一个新缓存的chron作业,而不是为用户创建新缓存。

Cake有许多很酷的触发器,比如afterSave(),你可以使用它来触发这种事情。如果这在你的情况下没有意义,那么你的chron工作应该没问题。

答案 1 :(得分:4)

听起来你或多或少想出了答案(自动创建缓存,而不是由用户请求触发)。

为此,请查看cake的AppShell类book talks about it here。然后,您可以将其链接到cron作业。如果您通过Cache::write创建文件,那么cake应该知道它是一个新的缓存文件并透明地读取它。你可能想留下“如果没有找到缓存”块,以防你的cronjob失败。

贝壳&amp;蛋糕中的任务很有趣,可以让您免费使用请求/响应模型。

答案 2 :(得分: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');

覆盖缓存的内容。

这样,每秒100个用户将始终从缓存中读取