PHP PEAR Cache_Lite

时间:2011-03-01 13:29:19

标签: php memcached pear

HI

由于我使用的是共享主机软件包,并且我无法使用PECL Memcache,我会很感激使用我自己的小缓存系统或使用PEAR Cache_Lite系统时我自己有些疑问。

所以这是我的功能:

<?php

//this one create a simple .txt file named by unique query_key string generated width e.g $file_name=md5("SELECT * FROM table"); content of that file is serialized value of mysql return

function write($query_key,$result)
{
  global $config;
  $new_file_name=md5($query_key);
  $result_to_write=serialize($result);  
  if($handle=opendir($config['cache_dir'])) 
  {
    $f=fopen($config['cache_dir'].$new_file_name.'.txt','w+');
    fwrite($f,$result_to_write);        
    fclose($f);
    closedir($handle);
  }
}

// this one reads content of file (serialized mysql return of unique query_key) if timeout hes not expired, and if it is it return false

function read($query_key,$timeout)
{
  global $config;
  $file_name=md5($query_key);
  if($handle=opendir($config['cache_dir'])) 
  {
    if(file_exists($config['cache_dir'].$file_name.'.txt'))
    {
      $last_accessed=filemtime($config['cache_dir'].$file_name.'.txt');
      $now=time();
      if(($now-$last_accessed)<$timeout)
      {
        $file=fopen($config['cache_dir'].$file_name.'.txt','rb');
        $f=fread($file,filesize($config['cache_dir'].$file_name.'.txt'));
        $array=unserialize($f);
        fclose($file);  
        closedir($handle);
      }else{ return FALSE; }
    }else{ return FALSE; }
  }
  if(!empty($array)) return $array;
  else return FALSE;
}

//and finally this one which is used when executing query, so it has timeout in seconds, if file (cached result) exists, and timeout has not expired, it returnt cached data , or it reads from database returns new result,and cache new result by writing new file

function cache($query)
{
  $timeout=600;
  $file_exists=read($query,$timeout);
  if($file_exists)
  {
    return $file_exists;
  }else{
    $result=get_rows($query);
    write($query,$result);
    return $result;
  }
}
?>

这个我的小“缓存系统”工作得非常好,正如我所看到的,PEAR Cache_Lite的工作方式几乎相同,而且由于我不熟悉梨缓存系统,我想知道哪些更好,更安全,在这两者之间使用更快的解决方案,以及为什么??

Thanx很多!!

1 个答案:

答案 0 :(得分:4)

就个人而言,我会使用一个库。编写缓存层似乎要困难得多。你不能做到这一点并不困难,但是很难将所有边缘情况和怪癖都赶出系统。你可以使用类似Cache_Lite的东西,但我会建议一个更好的缓存层。其中有一些(独立和框架出生)。以下是一些:

  • Zend_Cache - 您可以单独使用此功能。但它也经过精心设计和测试......

  • Cache_Lite - 如果您只想要文件缓存。它重量轻,但也不是非常灵活(但可能是你想要的)。

  • Kohana's cache。它相当灵活,但我不太确定与框架的其他部分分开是多么容易(没有经验)。

关于您的代码的一些评论:

  1. 我会使用不同的变量名。 $file_exists函数中的cache()是一个非常糟糕的名称。它应该是$cache_results之类的东西。使用语义来识别您的名字。

  2. 我真的将它包装在一个类中,这样你就可以更好地进行初始化。根据请求,您只需要执行一些操作,因此无需每次都执行此操作(稍等一些)。

  3. 清除您的统计信息缓存!每次请求运行clearstatcache() 一次。原因是PHP可以缓存无效的统计信息并返回file_existsfilemtime等错误信息。但它相当昂贵,所以我不会每次请求多次运行它... < / p>

  4. opendirread()完全不需要使用write()。如果要验证该目录是否存在,只需调用is_dir($dir)即可。现在,你正在打开一个手柄,什么都不做。

  5. read()write()都有资源泄漏,其中有路径可以打开目录但不关闭目录。虽然这在大多数情况下都不是一件大事,但要正确关闭资源。 (更好的是,完全消除呼叫)。

  6. 请勿将fopen(); fwrite(); fclose();用于此类操作。如果您在写入文件时出现另一个请求(这将导致部分读取),您可能会自己开枪。相反,使用file_put_contents($filename, $data, LOCK_EX);进行写作。它基本上是原子的(不完全,但足够接近你的目的)。我会在read()

    中阅读之前锁定文件
    $file=fopen($config['cache_dir'].$file_name.'.txt','rb');
    if (flock($file, LOCK_SH)) {
        $f=fread($file,filesize($config['cache_dir'].$file_name.'.txt'));
        flock($file, LOCK_UN);
    }