PHP缓存策略 - 天才还是纯粹的愚蠢?

时间:2014-07-13 05:17:19

标签: php caching

我有一个功能有限的共享主机。我无法使用Memcache和mod_cache。我想实现自己的PHP缓存方法来缓存负载密集型SQL查询的结果。在SQL中使用汇总表不是一个选项,因为查询采用了多个可以假设数千个不同值的参数(它是一个统计系统)。

我的想法是这样的:

function execQuery($parameter)
{
     $query = "SELECT ....... " . $parameter; //query code has been generated

     $rand = mt_rand(0,10); 
     //no need to check/save expiry dates,generate cache randomly for speed

     if($rand == 0)
     {
           //execute query normally and generate new cache
           $result = mysql_query($query);
           $md5 = md5($query); // the name of the cache file equals the md5 of the query
           $cache_file = fopen("/cache/" . $md5 ."php", "w");
           fwrite($cache_file, $result); // the result is written as php code generating a ready for use result array, code has to be modified I think
           //return the result
     }
     else
     {
            //cache will be used
            $md5 = md5($query);
            if(file_exists("/cache/" . $md5 ."php"))
            {
                  include("/cache/" . $md5 ."php");
                  return $result;
            }
            else
           {
                  //no cache exists, run query normally and generate cache
           }
     }   
}

您如何看待这个以及可能存在的陷阱?使用mt_rand,md5有什么含义?您认为他们会超出负载密集型查询吗?多个系统文件写入是否值得(每10次点击只能写一次,甚至可以增加)?

1 个答案:

答案 0 :(得分:1)

文件缓存是很多系统使用的东西(可能是因为很多主机不提供其他缓存机制),所以一般来说 - 这是很好的方法。但是,使用rand而不是修改日期,将无法很好地扩展。如果您有1000次访问,该怎么办?这意味着允许100个查询命中数据库。因此,您的方法应基于到期日期。此外,如果查询很昂贵,无论何时触发重新生成,touch文件(更新日期都会更新),因此其他命中也不会触发重新生成。

此外,您应该以检查文件是否存在以及它是否在同一步骤中过时的方式构建代码,并且只有一个代码用于生成:

function execQuery($parameter)
{
     $query = "SELECT ....... " . $parameter; //query code has been generated
     $md5 = md5($query); // the name of the cache file equals the md5 of the query
     $cache_file = "/cache/" . $md5 ."php");
     $expire = 600; // seconds


     if(!file_exists($cache_file) || mtime($cache_file) < time() - $expire)
     {
           touch($cache_file);
           //execute query normally and generate new cache
           $result = mysql_query($query);
           $fp = fopen($cache_file, "w");
           fwrite($fp, serialize($result)); // the result is written as php code generating a ready for use result array, code has to be modified I think
           fclose($fp);
     }
     return unserialize(file_get_contents($cache_file));   
}

您不应该保存由mysql_query返回的resource变量,而是实际获取数据(否则您将无法使用它)。

通常,缓存的工作原理是单次写入,多次读取,因此速度并不慢。当然,它比在内存中加载慢,但是大量读取的文件都会被操作系统缓存。