PHP缓存策略-天才还是愚蠢


PHP Cache Strategy - Genius or Sheer Stupidity?

我有一个功能有限的共享主机。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次命中只有一次写入,甚至可以增加)?

文件缓存是许多系统使用的东西(可能是因为许多主机不提供其他缓存机制),所以通常-这是一个很好的方法。然而,使用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变量,而应该实际获取数据(否则您将无法使用它)。

一般来说,缓存的工作原理是一次写,多次读,所以它不是很慢。当然,它比在内存中加载慢,但是大量读取的文件无论如何都会被操作系统缓存。