PHP三种缓存文件方法


下面总结了三种缓存文件方法,一种是nginx下的缓存fastcgi_cache和proxy_cache,一种利用memcache缓存,另一种是利用php文件缓存.


nginx有两种缓存机制:fastcgi_cache和proxy_cache


下面我们来说说这两种缓存机制的区别吧


proxy_cache作用是缓存后端服务器的内容,可能是任何内容,包括静态的和动态的


fastcgi_cache作用是缓存fastcgi生成的内容,很多情况是php生成的动态内容


proxy_cache缓存减少了nginx与后端通信的次数,节省了传输时间和后端带宽


fastcgi_cache缓存减少了nginx与php的通信次数,更减轻了php和数据库的压力


proxy_cache缓存设置


#注:proxy_temp_path和proxy_cache_path指定的路径必须在同一分区


proxy_temp_path /data0/proxy_temp_dir;


#设置Web缓存区名称为cache_one,内存缓存空间大小为200MB,1天没有被访问的内容自动清除,硬盘缓存空间大小为30GB。


proxy_cache_path  /data0/proxy_cache_dir  levels=1:2   keys_zone=cache_one:200m inactive=1d max_size=30g;


实例代码如下:

server
  {
    listen       80;
    server_name  www.phpfensi.com 192.168.8.42;
    index index.html index.htm;
    root  /data0/htdocs/www;  

    location /
    {
         #如果后端的服务器返回502、504、执行超时等错误,自动将请求转发到upstream负载均衡池中的另一台服务器,实现故障转移。
         proxy_next_upstream http_502 http_504 error timeout invalid_header;
         proxy_cache cache_one;
         #对不同的HTTP状态码设置不同的缓存时间
         proxy_cache_valid  200 304 12h;
         #以域名、URI、参数组合成Web缓存的Key值,Nginx根据Key值哈希,存储缓存内容到二级缓存目录内
         proxy_cache_key $host$uri$is_args$args;
         proxy_set_header Host  $host;
         proxy_set_header X-Forwarded-For  $remote_addr;
         proxy_pass http://backend_server;
         expires      1d;
    } 

    #用于清除缓存,假设一个URL为http://192.168.8.42/test.txt,通过访问http://192.168.8.42/purge/test.txt就可以清除该URL的缓存。
    location ~ /purge(/.*)
    {
     #设置只允许指定的IP或IP段才可以清除URL缓存。
     allow            127.0.0.1;
     allow            192.168.0.0/16;
     deny            all;
     proxy_cache_purge    cache_one   $host$1$is_args$args;
    }    

    #扩展名以.php、.jsp、.cgi结尾的动态应用程序不缓存。
    location ~ .*.(php|jsp|cgi)?$
    {
         proxy_set_header Host  $host;
         proxy_set_header X-Forwarded-For  $remote_addr;
         proxy_pass http://backend_server;
    } 

    access_log  off;
  }
} 

fastcgi_cache缓存设置


#定义缓存存放的文件夹,代码如下:


fastcgi_cache_path   /tt/cache  levels=1:2 keys_zone=NAME:2880m inactive=2d max_size=10G;


#定义缓存不同的url请求,代码如下:

fastcgi_cache_key "$scheme$request_method$host$uri$arg_filename$arg_x$arg_y"; 

server {
        listen       8080;
        server_name  www.example .com;
        location / {
            root   /www;
            index  index.html index.htm index.php;
        } 

        location ~ (|.php)$ {
            root           /www;
            fastcgi_pass   127.0.0.1:9000; 

            fastcgi_cache   NAME;
            fastcgi_cache_valid 200 48h;
            fastcgi_cache_min_uses  1;
            fastcgi_cache_use_stale error  timeout invalid_header http_500; 

            fastcgi_index  index.php;
            fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
            include        fastcgi.conf;
            #设置缓存的过程中发现无法获取cookie,经查需要定义这句话
            fastcgi_pass_header Set-Cookie;
        } 

        log_format  access  ‘$remote_addr - $remote_user [$time_local] "$request" ‘
              ‘$status $body_bytes_sent "$http_referer" ‘
              ‘"$http_user_agent" $http_x_forwarded_for‘;
access_log  /httplogs/access.log  access;
} 

总的来说 nginx的proxy_cache和fastcgi_cache的缓存配置差不多.


memcache缓存


在讨论memcache缓存之前,我们先了解下mysql的内存缓存吧.


mysql的内存缓存可以在my.cnf中指定大小:内存表和临时表不同,临时表也是存放内存中,临时表最大的内存需要通过tmp_table_size=128M设定,当数据查过临时表的最大值设定时,自动转为磁盘表,此时因需要进行IO操作,性能会大大下降,而内存表不会,内存满了后,会提示数据满错误,代码如下:


  1. create table test
  2. (
  3. id int unsigned not null auto_increment primary key
  4. state char(10),
  5. type char(20),
  6. date char(30)
  7. )engine=memory default charset=utf8

内存表的特性:


1.内存表的表定义存放在磁盘上,扩展名为.frm,所以重启不会丢失


2.内存表的数据是存放在内存中,重启会丢失数据


3.内存表使用一个固定的长度格式


4.内存表不支持blob或text列,比如varchar与text字段就不会被支持


5.内存表支持auto_increment列和对可包含null值的列的索引


6.内存表不支持事物


7.内存表是表锁,当修改频繁时,性能可能会下降


分享一个存php缓存类,代码如下:

class Cache
{ 

    private static $_instance;
    protected $_cacheId = null; 

    const CLEANING_MODE_ALL  = ‘all‘;
    const CLEANING_MODE_OLD = ‘old‘; 

    protected $_options = array(
        ‘cache_dir‘ => null,                  //数据缓存目录
        ‘life_time‘ => 7200,                  //缓存时间
        ‘page_dir‘ => null,                   //文本缓存目录
        ‘cache_prefix‘ => ‘cache_‘        //缓存前缀
    ); 

    private function __construct(){} 

    //创建__clone方法防止对象被复制克隆
    private function __clone(){} 

    /**
     * 取缓存对象,如果存在直接返回,如果不存在实例化本身
     * @return object cache
     */
    public static function getInstance(){ 

        if(! self::$_instance){ 

            self::$_instance = new self();
        } 

        return self::$_instance;
    } 

    /**
     * 设置缓存参数集
     * @param array $options 要设置的缓存参数集
     */
    public function setOptions($options = array()){ 

        while (list($name, $value) = each($options)) {
            $this->setOption($name, $value);
        }
    } 

    /**
     * 取得当前缓存参数,如果$name为空返回全部参数,否则返回该参数值
     * @param string $name 要返回的参数名称
     * @return string or array $option;
     */
    public function getOption($name = null){ 

        if(null === $name)
            return $this->_options; 

        if (!is_string($name)) {
            throwException("不正确的参数名称 : $name");
        } 

        if (array_key_exists($name, $this->_options)){
            return $this->_options[$name];
        }
    } 

    /**
     * 设置缓存参数
     * @param array $options 要设置的缓存参数
     */
    protected function setOption($name, $value){ 

        if (!is_string($name)) {
            throwException("不正确的参数名称 : $name");
        }
        $name = strtolower($name);
        if (array_key_exists($name, $this->getOption())){
            $this->_options[$name] = $value;
        } 

        if ($this->_options[‘cache_dir‘] === null) {
            $this->setOption(‘cache_dir‘, $this->getTmpDir() . DIRECTORY_SEPARATOR);
        } 

        if ($this->_options[‘page_dir‘] === null) {
            $this->setOption(‘page_dir‘, $this->getTmpDir() . DIRECTORY_SEPARATOR);
        }
    } 

    /**
     * 读取数据缓存,如果不存在或过期,返回false
     * @param string $id 缓存ID
     * @return false or data
     */
    public function load($id){ 

        $this->_cacheId = $id;
        $file = $this->getOption(‘cache_dir‘) . $this->getOption(‘cache_prefix‘) . $this->_cacheId; 

        if (@filemtime($file) >= time()){ 

            return unserialize(file_get_contents($file));
        } else {
            @unlink($file);
            return false;
        }
    } 

    /**
     * 保存数据缓存,并设置缓存过期时间
     * @param array or string $data 要缓存的数据
     * @param int $lifeTime 缓存过期时间
     */
    public function save($data, $lifeTime = null){ 

        if(null !== $lifeTime)
            $this->setOption(‘life_time‘, $lifeTime); 

        $file = $this->getOption(‘cache_dir‘) . $this->getOption(‘cache_prefix‘) . $this->_cacheId;
        $data = serialize($data);
        @file_put_contents($file, $data);
        @chmod($file, 0777);
        @touch($file, time() + $this->getOption(‘life_time‘]));
    }    

    /**
     * 读取输出缓存,如果不存在或缓存过期将重新开启输出缓存
     * @param string $id 缓存ID
     */
    public function start($id){ 

        $this->_cacheId = $id;
        $file = $this->getOption(‘page_dir‘) . $this->getOption(‘cache_prefix‘) . $this->_cacheId; 

        if (@filemtime($file) >= time()){ 

            return file_get_contents($file);
        } else {
            @unlink($file);
            ob_start();
            return false;
        }
    } 

    /**
     * 删除指定ID缓存
     * @param string $id 缓存ID
     */
    public function remove($id){ 

        $this->_cacheId = $id;
        //删除附合条件的数据缓存
        $file = $this->getOption(‘cache_dir‘) . $this->getOption(‘cache_prefix‘) . $this->_cacheId;
        @unlink($file);
        //删除附合条件的输出缓存
        $file = $this->getOption(‘page_dir‘) . $this->getOption(‘cache_prefix‘) . $this->_cacheId;
        @unlink($file);
    } 

    /**
     * 保存输出缓存,并设置缓存过期时间
     * @param int $lifeTime 缓存过期时间
     */
    public function end($lifeTime = null){ 

        if(null !== $lifeTime)
            $this->setOption(‘life_time‘, $lifeTime); 

        $file = $this->getOption(‘page_dir‘) . $this->getOption(‘cache_prefix‘) . $this->_cacheId;
        $data = ob_get_contents();
        ob_end_clean();
        @file_put_contents($file, $data);
        @chmod($file, 0777);
        @touch($file, time() + $this->getOption(‘life_time‘]));
    } 

    /**
     * 根据参数清除相应缓存
     * @param string $mode 缓存类型,包括(CLEANING_MODE_ALL:所有缓存, CLEANING_MODE_OLD: 过期缓存)
     */
    public function clear($mode = CLEANING_MODE_OLD){ 

        $dirs = array(‘cache_dir‘, ‘page_dir‘);
        foreach($dirs as $value){
            if(null != $this->getOption($value)){
                $files = scandir($this->getOption($value));
                switch ($mode) { 

                    case CLEANING_MODE_ALL:
                    default:
                        foreach ($files as $val){
                            @unlink($this->getOption($value) . $val);
                        }
                        break; 

                    case CLEANING_MODE_OLD:
                    default:
                        foreach ($files as $val){
                            if (filemtime($this->getOption($value) . $val) < time()){
                                @unlink($this->getOption($value) . $val);
                            }
                        }
                        break;
                }
            }
        }
    } 

    /**
     * 取临时文件夹为缓存文件夹
     * @return $dir 临时文件夹路径
     */
    public function getTmpDir(){ 

        $tmpdir = array();
        foreach (array($_ENV, $_SERVER) as $tab) {
            foreach (array(‘TMPDIR‘, ‘TEMP‘, ‘TMP‘, ‘windir‘, ‘SystemRoot‘) as $key) {
                if (isset($tab[$key])) {
                    if (($key == ‘windir‘) or ($key == ‘SystemRoot‘)) {
                        $dir = realpath($tab[$key] . ‘\temp‘);
                    } else {
                        $dir = realpath($tab[$key]);
                    }
                    if ($this->_isGoodTmpDir($dir)) {
                        return $dir;
                    }
                }
            }
        }
        $upload = ini_get(‘upload_tmp_dir‘);
        if ($upload) {
            $dir = realpath($upload);
            if ($this->_isGoodTmpDir($dir)) {
                return $dir;
            }
        }
        if (function_exists(‘sys_get_temp_dir‘)) {
            $dir = sys_get_temp_dir();
            if ($this->_isGoodTmpDir($dir)) {
                return $dir;
            }
        }
        //通过尝试创建一个临时文件来检测
        $tempFile = tempnam(md5(uniqid(rand(), TRUE)), ‘‘);
        if ($tempFile) {
            $dir = realpath(dirname($tempFile));
            unlink($tempFile);
            if ($this->_isGoodTmpDir($dir)) {
                return $dir;
            }
        }
        if ($this->_isGoodTmpDir(‘/tmp‘)) {
            return ‘/tmp‘;
        }
        if ($this->_isGoodTmpDir(‘\temp‘)) {
            return ‘\temp‘;
        }
        throw new Exception(‘无法确定临时目录,请手动指定cache_dir‘, E_USER_ERROR);
    } 

    /**
     * 验证给定的临时目录是可读和可写的
     *
     * @param string $dir 临时文件夹路径
     * @return boolean true or false 临时文件夹路径是否可读写
     */
    protected function _isGoodTmpDir($dir){ 

        if (is_readable($dir)) {
            if (is_writable($dir)) {
                return true;
            }
        }
        return false;
    } 
时间: 2024-10-10 18:31:42

PHP三种缓存文件方法的相关文章

谈谈vector容器的三种遍历方法

说明:本文仅供学习交流,转载请标明出处,欢迎转载! vector容器是最简单的顺序容器,其使用方法类似于数组,实际上vector的底层实现就是采用动态数组.在编写程序的过程中,常常会变量容器中的元素,那么如何遍历这些元素呢?本文给出三种遍历方法. 方法一:采用下标遍历 由于vector容器就是对一个动态数组的包装,所以在vector容器的内部,重载了[]运算符,函数原型为:reference operator [] (size_type n);所以我们可以采用类似于数组的方式来访问vector容

android开发中监听器的三种实现方法(OnClickListener)

Android开发中监听器的实现有三种方法,对于初学者来说,能够很好地理解这三种方法,将能更好地增进自己对android中监听器的理解. 一.什么是监听器. 监听器是一个存在于View类下的接口,一般以On******Llistener命名,实现该接口需要复写相应的on****(View v)方法(如onClick(View v)). 二.监听器的三种实现方法 (以OnClickListener为例) 方法一:在Activity中定义一个内部类继承监听器接口(这里是OnClickListener

js oop中的三种继承方法

JS OOP 中的三种继承方法: 很多读者关于js opp的继承比较模糊,本文总结了oop中的三种继承方法,以助于读者进行区分. <继承使用一个子类继承另一个父类,子类可以自动拥有父类的属性和方法.(继承的两方,发生在两个类之间)> 一.通过object实现继承 1:定义父类 function Parent(){} 2:定义子类 funtion Son(){} 3:通过原型给Object对象添加一个扩展方法. Object.prototype.customExtend = function(p

Android中常用的三种存储方法浅析

Android中常用的三种存储方法浅析 Android中数据存储有5种方式: [1]使用SharedPreferences存储数据 [2]文件存储数据 [3]SQLite数据库存储数据 [4]使用ContentProvider存储数据 [5]网络存储数据 在这里我只总结了三种我用到过的或即将可能用到的三种存储方法. 一.使用SharedPreferences存储数据 SharedPreferences是Android平台上一个轻量级的存储类,主要是保存一些常用的配置信息比如窗口状态,它的本质是基

Jquery中each的三种遍历方法

Jquery中each的三种遍历方法 $.post("urladdr", { "data" : "data" }, function(data) { $.each(data, function(n,value) { });}); 1.选择器+遍历 $('div').each(function (i){ i就是索引值 this 表示获取遍历每一个dom对象 }); 2.选择器+遍历 $('div').each(function (index,dom

C#使用DataSet Datatable更新数据库的三种实现方法

本文以实例形式讲述了使用DataSet Datatable更新数据库的三种实现方法,包括CommandBuilder 方法.DataAdapter 更新数据源以及使用sql语句更新.分享给大家供大家参考之用.具体方法如下: 一.自动生成命令的条件 CommandBuilder 方法 a)动态指定 SelectCommand 属性 b)利用 CommandBuilder 对象自动生成 DataAdapter 的 DeleteCommand.InsertCommand 和 UpdateCommand

Java中Map的三种遍历方法

Map的三种遍历方法: 1. 使用keySet遍历,while循环: 2. 使用entrySet遍历,while循环: 3. 使用for循环遍历. 告诉您们一个小秘密: (下↓面是测试代码,最爱看代码了,啰嗦再多也没用) 一般人我不告诉他哦. import java.util.*; //0 我的Main界面 public class MapTraverse { public static void main(String[] args) { String[] str = {"I love you

JS面向对象(3) -- Object类,静态属性,闭包,私有属性, call和apply的使用,继承的三种实现方法

相关链接: JS面向对象(1) -- 简介,入门,系统常用类,自定义类,constructor,typeof,instanceof,对象在内存中的表现形式 JS面向对象(2) -- this的使用,对象之间的赋值,for...in语句,delete使用,成员方法,json对象的使用,prototype的使用,原型继承与原型链 JS面向对象(3) -- Object类,静态属性,闭包,私有属性, call和apply的使用,继承的三种实现方法 1.Object类 在JS中,Object是所有类的基

Liunx 环境下vsftpd的三种实现方法(超详细参数)

以下文章介绍Liunx 环境下vsftpd的三种实现方法 ftp://vsftpd.beasts.org/users/cevans/vsftpd-2.0.3.tar.gz,目前已经到2.0.3版本.假设我们已经将vsftpd-2.0.3.tar.gz文件下载到服务器的/home/xuchen目录 代码: # cd /home/xuchen # tar xzvf vsftpd-2.0.3.tar.gz //解压缩程序 # cd vsftpd-2.0.3 三.三种方式的实现