php专区

 首页 > php专区 > PHP应用 > 常用功能 > PHP中常用的缓存技术介绍 - php高级应用

PHP中常用的缓存技术介绍 - php高级应用

分享到:
【字体:
导读:
          数据缓存:这里所说的数据缓存是指数据库查询缓存,每次访问页面的时候,都会先检测相应的缓存数据是否存在,如果不存在,就连接数据库,得到数据,并把查询结果序列化后保存到文件中...

PHP中常用的缓存技术介绍

数据缓存:这里所说的数据缓存是指数据库查询缓存,每次访问页面的时候,都会先检测相应的缓存数据是否存在,如果不存在,就连接数据库,得到数据,并把查询结果序列化后保存到文件中,以后同样的查询结果就直接从缓存文件中获得,代码如下:

  1. $sql = 'SELECT * FROM users'
  2. $key = md5($sql);   //memcached 对象标识符 
  3. if ( !($datas = $mc->get($key)) ) { 
  4.     //    在 memcached 中未获取到缓存数据,则使用数据库查询获取记录集。 
  5.     echo "n".str_pad('Read datas from MySQL.', 60, '_')."n"
  6.     $conn = mysql_connect('localhost''test''test'); 
  7.     mysql_select_db('test'); 
  8.     $result = mysql_query($sql); 
  9.       while ($row = mysql_fetch_object($result)) 
  10.         $datas[] = $row
  11.     //    将数据库中获取到的结果集数据保存到 memcached 中,以供下次访问时使用。 
  12.     $mc->add($key$datas); 
  13. else { 
  14.       echo "n".str_pad('Read datas from memcached.', 60, '_')."n"
  15. var_dump($datas); 
  16. ?> 

页面缓存:每次访问页面的时候,都会先检测相应的缓存页面文件是否存在,如果不存在,就连接数据库,得到数据,显示页面并同时生成缓存页面文件,这样下次访问的时候页面文件就发挥作用了,模板引擎和网上常见的一些缓存类通常有此功能,代码如下:

  1. define('DIRECTORY_SEPARATOR','/'); 
  2. define('FOPEN_WRITE_CREATE_DESTRUCTIVE','wb'); 
  3. define('FOPEN_WRITE_CREATE','ab'); 
  4. define('DIR_WRITE_MODE', 0777); 
  5. class FileCache { 
  6.  
  7.  /** 
  8.      * 缓存路径 
  9.      * 
  10.      * @access private 
  11.      * @var string 
  12.      */ 
  13.  private $_cache_path
  14.  
  15.  /** 
  16.      * 缓存过期时间,单位是秒second 
  17.      * 
  18.      * @access private 
  19.      * @var int 
  20.      */ 
  21.  private $_cache_expire
  22.  
  23.  /** 
  24.      * 解析函数,设置缓存过期实践和存储路径 
  25.      *  
  26.      * @access public 
  27.      * @return void 
  28.      */ 
  29.  public function __construct($expire$cache_path
  30.  { 
  31.   $this->_cache_expire = $expire
  32.   $this->_cache_path = $cache_path
  33.  } 
  34.  
  35.  /** 
  36.      * 缓存文件名 
  37.      *  
  38.      * @access public 
  39.      * @param  string $key 
  40.      * @return void 
  41.      */ 
  42.  private function _file($key
  43.  { 
  44.   return $this->_cache_path . md5($key); 
  45.  } 
  46.  
  47.  /** 
  48.      * 设置缓存 
  49.      *  
  50.      * @access public 
  51.      * @param  string $key 缓存的唯一键 
  52.      * @param  string $data 缓存的内容 
  53.      * @return bool 
  54.      */ 
  55.  public function set($key$data
  56.  { 
  57.   $value = serialize($data); 
  58.    
  59.   $file = $this->_file($key); 
  60.    
  61.      return $this->write_file($file$value); 
  62.  } 
  63.  
  64.  /** 
  65.      * 获取缓存 
  66.      *  
  67.      * @access public 
  68.      * @param  string $key 缓存的唯一键 
  69.      * @return mixed 
  70.      */ 
  71.  public function get($key
  72.  { 
  73.   $file = $this->_file($key); 
  74.    
  75.   /** 文件不存在或目录不可写 */ 
  76.   if (!file_exists($file) || !$this->is_really_writable($file)) 
  77.   { 
  78.    return false; 
  79.   } 
  80.    
  81.   /** 缓存没有过期,仍然可用 */ 
  82.   if ( time() < (filemtime($file) + $this->_cache_expire) )  
  83.   { 
  84.     
  85.    $data = $this->read_file($file); 
  86.     
  87.    if(FALSE !== $data
  88.    { 
  89.     return unserialize($data); 
  90.    } 
  91.     
  92.    return FALSE; 
  93.   } 
  94.    
  95.   /** 缓存过期,删除之 */ 
  96.   @unlink($file); 
  97.   return FALSE; 
  98.   } 
  99.    
  100.   function read_file($file
  101.  { 
  102.   if ( ! file_exists($file)) 
  103.   { 
  104.    return FALSE; 
  105.   } 
  106.  
  107.   if (function_exists('file_get_contents')) 
  108.   { 
  109.    return file_get_contents($file);   
  110.   } 
  111.  
  112.   if ( ! $fp = @fopen($file, FOPEN_READ)) 
  113.   { 
  114.    return FALSE; 
  115.   } 
  116.    
  117.   flock($fp, LOCK_SH);//读取之前加上共享锁 
  118.  
  119.   $data = ''
  120.   if (filesize($file) > 0) 
  121.   { 
  122.    $data =& fread($fpfilesize($file)); 
  123.   } 
  124.  
  125.   flock($fp, LOCK_UN);//释放锁 
  126.   fclose($fp); 
  127.  
  128.   return $data
  129.  } 
  130.  
  131.   function write_file($path$data$mode = FOPEN_WRITE_CREATE_DESTRUCTIVE) 
  132.  { 
  133.   if ( ! $fp = @fopen($path$mode)) 
  134.   { 
  135.    return FALSE; 
  136.   } 
  137.    
  138.   flock($fp, LOCK_EX); 
  139.   fwrite($fp$data); 
  140.   flock($fp, LOCK_UN); 
  141.   fclose($fp);  
  142.  
  143.   return TRUE; 
  144.  } 
  145.  function is_really_writable($file)//兼容各平台判断文件是否有写入权限 
  146.  {  
  147.   // If we're on a Unix server with safe_mode off we call is_writable 
  148.   if (DIRECTORY_SEPARATOR == '/' AND @ini_get("safe_mode") == FALSE) 
  149.   { 
  150.    return is_writable($file); 
  151.   } 
  152.  
  153.   // For windows servers and safe_mode "on" installations we'll actually 
  154.   // write a file then read it.  Bah... 
  155.   if (is_dir($file)) 
  156.   { 
  157.    $file = rtrim($file'/').'/'.md5(rand(1,100)); 
  158.  
  159.    if (($fp = @fopen($file, FOPEN_WRITE_CREATE)) === FALSE) 
  160.    { 
  161.     return FALSE; 
  162.    } 
  163.  
  164.    fclose($fp); 
  165.    @chmod($file, DIR_WRITE_MODE); 
  166.    @unlink($file); 
  167.    return TRUE; 
  168.   } 
  169.   elseif (($fp = @fopen($file, FOPEN_WRITE_CREATE)) === FALSE) 
  170.   { 
  171.    return FALSE; 
  172.   } 
  173.  
  174.   fclose($fp); 
  175.   return TRUE; 
  176.  } 
  177. $cache = new FileCache(30,'cache/'); 
  178. $cache->set('test','this is a test.'); 
  179. print $cache->get('test'); 
  180. /* End of file FlieCache.php */ 

内存缓存:Memcached是高性能的,分布式的内存对象缓存系统,用于在动态应用中减少数据库负载,提升访问速度.

dbcached 是一款基于 Memcached 和 NMDB 的分布式 key-value 数据库内存缓存系统.

以上的缓存技术虽然能很好的解决频繁查询数据库的问题,但其缺点在在于数据无时效性,下面我给出我在项目中常用的方法,代码如下:

  1. class MemcacheModel { 
  2. private $mc = null; 
  3. /** 
  4. * 构造方法,用于添加服务器并创建memcahced对象 
  5. */ 
  6. function __construct(){ 
  7. $params = func_get_args(); 
  8. $mc = new Memcache; 
  9. //如果有多个memcache服务器 
  10. ifcount($params) > 1){ 
  11. foreach ($params as $v){ 
  12. call_user_func_array(array($mc'addServer'), $v); 
  13. //如果只有一个memcache服务器 
  14. else { 
  15. call_user_func_array(array($mc'addServer'), $params[0]); 
  16. $this->mc=$mc
  17. /** 
  18. * 获取memcached对象 
  19. * @return object memcached对象 
  20. */ 
  21. function getMem(){ 
  22. return $this->mc; 
  23. /** 
  24. * 检查mem是否连接成功 
  25. * @return bool 连接成功返回true,否则返回false 
  26. */ 
  27. function mem_connect_error(){ 
  28. $stats=$this->mc->getStats(); 
  29. if(emptyempty($stats)){ 
  30. return false; 
  31. }else
  32. return true; 
  33. private function addKey($tabName$key){ 
  34. $keys=$this->mc->get($tabName); 
  35. if(emptyempty($keys)){ 
  36. $keys=array(); 
  37. //如果key不存在,就添加一个 
  38. if(!in_array($key$keys)) { 
  39. $keys[]=$key;  //将新的key添加到本表的keys中 
  40. $this->mc->set($tabName$keys, MEMCACHE_COMPRESSED, 0); 
  41. return true;   //不存在返回true 
  42. }else
  43. return false;  //存在返回false 
  44. /** 
  45. * 向memcache中添加数据 
  46. * @param string $tabName 需要缓存数据表的表名 
  47. * @param string $sql 使用sql作为memcache的key 
  48. * @param mixed $data 需要缓存的数据 
  49. */ 
  50. function addCache($tabName$sql$data){ 
  51. $key=md5($sql); 
  52. //如果不存在 
  53. if($this->addKey($tabName$key)){ 
  54. $this->mc->set($key$data, MEMCACHE_COMPRESSED, 0); 
  55. /** 
  56. * 获取memcahce中保存的数据 
  57. * @param string $sql 使用SQL的key 
  58. * @return mixed 返回缓存中的数据 
  59. */ 
  60. function getCache($sql){ 
  61. $key=md5($sql); 
  62. return $this->mc->get($key); 
  63.  
  64. /** 
  65. * 删除和同一个表相关的所有缓存 
  66. * @param string $tabName 数据表的表名 
  67. */  
  68. function delCache($tabName){ 
  69. $keys=$this->mc->get($tabName); 
  70. //删除同一个表的所有缓存 
  71. if(!emptyempty($keys)){ 
  72. foreach($keys as $key){ 
  73. $this->mc->delete($key, 0); //0 表示立刻删除 
  74. //删除表的所有sql的key 
  75. $this->mc->delete($tabName, 0);  
  76. /** 
  77. * 删除单独一个语句的缓存 
  78. * @param string $sql 执行的SQL语句 
  79. */ 
  80. function delone($sql){ 
  81. $key=md5($sql); 
  82. $this->mc->delete($key, 0); //0 表示立刻删除 

时间触发缓存:检查文件是否存在并且时间戳小于设置的过期时间,如果文件修改的时间戳比当前时间戳减去过期时间戳大,那么就用缓存,否则更新缓存.

设定时间内不去判断数据是否要更新,过了设定时间再更新缓存,以上只适合对时效性要求不高的情况下使用,否则请看下面.

内容触发缓存:当插入数据或更新数据时,强制更新缓存.

在这里我们可以看到,当有大量数据频繁需要更新时,最后都要涉及磁盘读写操作,怎么解决呢?我在日常项目中,通常并不缓存所有内容,而是缓存一部分不经常变的内容来解决,但在大负荷的情况下,最好要用共享内存做缓存系统.

到这里PHP缓存也许有点解决方案了,但其缺点是,因为每次请求仍然要经过PHP解析,在大负荷的情况下效率问题还是比效严重,在这种情况下,也许会用到静态缓存.

静态缓存:这里所说的静态缓存是指HTML缓存,HTML缓存一般是无需判断数据是否要更新的,因为通常在使用HTML的场合一般是不经常变动内容的页面,数据更新的时候把HTML也强制更新一下就可以了.

也有像thinkphp的静态缓存,ThinkPHP官方手册写道静态规则的定义有三种方式,代码如下:

  1. Return Array( 
  2.  
  3. ‘ActionName’=>array(‘静态规则’,’静态缓存有效期’,’附加规则’), //第一种 
  4.  
  5. ‘ModuleName:ActionName’=>array(‘静态规则’,’静态缓存有效期’,’附加规则’),//第二种 
  6.  
  7. ‘*’=>array(‘静态规则’,’静态缓存有效期’,’附加规则’),//第三种 
  8.  
  9. …更多操作的静态规则 
  10.  

第一种是定义全局的操作静态规则,例如定义所有的read操作的静态规则为:'read'=>array('{id}','60').

其中,{id} 表示取$_GET[‘id’] 为静态缓存文件名,第二个参数表示缓存60秒.

第二种是定义某个模块的操作的静态规则,例如,我们需要定义Blog模块的read操作进行静态缓存.

‘Blog:read’=>array(‘{id}’,-1).

第三种方式是定义全局的静态缓存规则,这个属于特殊情况下的使用,任何模块的操作都适用,例如:

‘*’=>array(‘{$_SERVER.REQUEST_URI|md5}’),根据当前的URL进行缓存。

我这里在静态缓存规则文件htmls.php中写,代码如下:

array('{:action}', -1),//-1表示永久缓存  );?>   

SMARTY缓存,代码如下:

  1. require('./smarty/Smarty.class.php'); 
  2. $smarty = new Smarty; 
  3.  
  4. $smarty->caching = true; 
  5.  
  6. if(!$smarty->is_cached('index.tpl')) { 
  7.     // No cache available, do variable assignments here. 
  8.     $contents = get_database_contents(); 
  9.     $smarty->assign($contents); 
  10. $smarty->display('index.tpl'); 
  11. ?> 
分享到:
PHP脚本实现Magento权限设置与缓存清理 -...
PHP脚本实现Magento权限设置与缓存清理 PHP脚本实现Magento权限设置与缓存清理的实例代码有需要的朋友可参考一下.PHP实例代码如下:  
微信公众平台消息接口(PHP)-官方的Demo有...
微信公众平台消息接口(PHP)-官方的Demo有问题 微信公众平台消息接口(PHP)-官方的Demo有问题,下面个人进行了处理,事例代码也跑不通,我研究了一番,终于搞定. 首先:在你的服务器上上传好一个接口文件,如http://www.phpfensi.com/weixin.php  内容如下:   然后:设置回复接口,填好UR...
  •         php迷,一个php技术的分享社区,专属您自己的技术摘抄本、收藏夹。
  • 在这里……