标签归档:缓存

关于缓存

维基百科中有这样一段描述: 凡是位于速度相差较大的两种硬件之间的,用于协调两者数据传输速度差异的结构,均可称之为Cache。 从最初始的处理器与内存间的Cache开始,都是为了让数据访问的速度适应CPU的处理速度, 其基于的原理是内存中“程序执行与数据访问的局域性行为”。

处理器缓存

在处理器与物理内存间有三级缓存,如下图: 

这是《深入理解计算机系统》上的一张图,对于每一层,位于上层的更快更小的存储设备作为位于下层更大更慢的存储设备的缓存。 从物理内存往上越往处理器方向走,存储设备的成本越高,并且更小,访问的速度更快。 它们是作为存储在更大更慢的存储设备的缓存而存在,它们的作用在于协调处理器与物理内存间的传输数据不一致。 但是把内存单独拉出来说,它也是一种缓存,它的作用也是为了将硬盘或其它较慢存储介质中的数据更快的提供给处理器。

DNS缓存

DNS(域名解析系统)缓存是指当第一次访问某个站点的时候,客户端会向DNS服务器发出解析请求, 然后把信息保存在本机的DNS缓存以备再次访问。启用DNS缓存能提高网络访问速度,相应地,计算机的安全性降低了。

HTTP协议缓存

HTTP为提高性能,减少网络传输的信息量,从而使用了缓存。 HTTP协议缓存的目标是去除许多情况下对于发送请求的的需求和去除许多情况下发送完整请求的需求。 在HTTP协议中使用截止模型和证实模型来实现缓存。 协议它只是协议,只是一种通行的建议和规范,关键还是看客户端的实现。 比较直观的体现是:当第一次去一个网站时加载会比较慢,但再次打开这个网站时速度会快很多。 这是由于基于HTTP协议,浏览器客户端将一些CSS,图片等文件都缓存在本地,从而不再需要从服务器读取。

DNS缓存、HTTP协议缓存的作用与处理器缓存有一些不同,虽然也是协调数据传输速度的差异,但是其本质的差别是它已不再是纯粹的两种硬件之间的差异, 而是引入了网络的元素,换一种表示方式:凡是位于速度相差较大的两种实体之间的,用于协调两者数据传输速度差异的结构,均可称之为Cache。

数据库系统缓存

这里没有用数据库缓存是因为数据库与数据库系统在概念上不是一回事。数据库是“按照数据结构来组织、存储和管理数据的仓库”。 而数据库系统是一个实际可运行的存储、维护和应用系统提供数据的软件系统,是存储介质、处理对象和管理系统的集合体。 我们平时所说的数据库缓存是数据库系统所提供的缓存功能。

以MySQL为例,我们使用最多的是查询缓存(Query Cache)。 它的实现过程不是很复杂,当客户端请求了一个查询后,MySQL通过特定的Hash算法生成一个标识用的hash值, 得MySQL计算完后,返回的结果集将与这个生成的hash值对应存放在内存中。若此缓存没有过期时, 下一次相同的请求过来时将直接返回结果,不再需要SQL解析,计算等操作。

PHP内存管理中的缓存

PHP内存管理中的缓存也是基于“程序执行与数据访问的局域性行为”的原理。 引入缓存,就是为了减少小块内存块的查询次数,为最近访问的数据提供更快的访问方式。 其实现过程主要包括以下的一些活动:

  • 标识缓存和缓存的大小限制,即何时使用缓存,在某些情况下可以以最少的修改禁用掉缓存
  • 缓存的存储结构,即缓存的存放位置、结构和存放的逻辑
  • 初始化缓存
  • 获取缓存中内容
  • 写入缓存
  • 释放缓存或者清空缓存列表

文件缓存

此处的文件缓存是指在应用开发过程中将一些中间结果存放在文件,以备下次使用。 如在PHP中一些模板系统的实现,以其规则编写了模板文件,生成中间的PHP文件,如果用户调用某个页面则直接访问PHP页面,而跳过了模板的解析过程

以上三种缓存与前面也不一样,它实际上是将一些需要计算后的结果缓存,下次直接返回计算后的结果。依此,则缓存的表述可以再次修改为: 凡是获取数据速度相差较大的两种实体之间的,用于协调两者数据传输速度差异的结构,均可称之为Cache。

Yii框架中有点意思的文件缓存

Yii框架中有点意思的文件缓存

在Yii框架的framework/caching目录下是Yii框架的所有缓存操作。包括文件缓存,APC缓存、Db缓存,Memcache缓存等。 今天我们要说的是文件缓存。

【文件和类结构】

它总共包括CFileCache.php、CCache.php和接口文件。 缓存基类CCache抽象类实现了CApplicationComponent类,ICache, ArrayAccess接口。 实现类CFileCache继承自CCache基类。其它如Memcache等缓存也是继承这个基类。 在ICache接口中统一缓存接口,在CCache基类中统一对外的接口,以类似于模板方法模式的方式将对于增加,修改,删除操作延迟到子类实现。

【缓存方案】

指定缓存目录,以一条数据一个文件的方式存储。序列化使用PHP自带的serialize函数。 如果缓存数据过多,作者建议使用多级目录,多级目录会自动生成,默认为0,即当前目录,推荐使用3级以下的子目录。 对于缓存过期是以文件的修改时间为准(filemtime函数)。在获取数据时,如果文件过期,则取的数据为空。

【有点意思的地方】

个人觉得有点意思的地方在于其对于过期缓存的批量处理,在程序中作者称其为garbage collection。 看其实现代码:

if(!$this->_gced && mt_rand(0,1000000)<$this->_gcProbability)
{
    $this->gc();    //  清除过期的缓存文件
    $this->_gced=true;
}

各位看官,你应该知道这段代码是啥意思了。 有点意思的地方是和PHP源码中对于session过期的处理。如下所示源码:

if (PS(mod_data) && PS(gc_probability) > 0) {
    int nrdels = -1;

    nrand = (int) ((float) PS(gc_divisor) * php_combined_lcg(TSRMLS_C));
    if (nrand < PS(gc_probability)) {
        //  调用定义的垃圾收集方法
        PS(mod)->s_gc(&PS(mod_data), PS(gc_maxlifetime), &nrdels TSRMLS_CC);
        ...
    }
}

对比下变量名,对比下调用方式。 ^_^

PHP缓存 Cache Lite源码总结

PHP缓存 Cache Lite源码总结

1、【设置参数的方法】
在构造方法中调用对象方法setOption设置类私有变量的值,从而完成对象的初始化操作。
在setOption方法中通过判断$name是否为$availableOptions数组中的一员来设置初始值。
感觉有些坏味道

2、【缓存文件命名规则】
命名规则对fileNameProtection参数有两种设置方法
如果此参数为真,则对于$group和$id进行md5加密,否则直接使用这两个字段
默认情况下使用md5加密后的名称
如下所示代码:

1
2
3
4
5
 if ($this->_fileNameProtection) {
         $suffix = 'cache_'.md5($group).'_'.md5($id);
 } else {
         $suffix = 'cache_'.$group.'_'.$id;
  }

3、【缓存路径设置规则】
如果设置了hashedDirectoryLevel参数,则会在用户所给的缓存地址(cacheDir参数)后添加多层(hashedDirectoryLevel层)目录,所有的目录以cache_开头
默认hashedDirectoryLevel的值为0,即不添加嵌套目录
如下所示代码:

1
2
3
4
5
6
7
        $root = $this->_cacheDir;    //    用户所给的缓存地址
        if ($this->_hashedDirectoryLevel>0) {
            $hash = md5($suffix);
            for ($i=0 ; $i<$this->_hashedDirectoryLevel ; $i++) {
                $root = $root . 'cache_' . substr($hash, 0, $i + 1) . '/';
            }   
        }

4、【基于内存的缓存】
在缓存参数中我们可以看到有一个memoryCaching参数,此参数默认情况下为false,
对于这个内存缓存,我有些疑惑:

1、基于apache2服务器的PHP页面,每次访问都会有一个apache线程处理这个请求,而在每个线程中,这些内存缓存都是以对象属性的形式存在,则在各线程间如何共享?这样存在的意义是什么?
2、如果是在一次执行中进行缓存,那这样做的意义又有多大呢?


5、【过期时间的控制】
在每次读取缓存时间都会调用_setRefreshTime方法刷新此前时间,
$this->_refreshTime = time() – $this->_lifeTime;
然后在取数据时判断缓存文件的创建时间是否比_refreshTime大

1
2
3
     if ((file_exists($this->_file)) && (@filemtime($this->_file) > $this->_refreshTime)) {
                    $data = $this->_read();
               }

6、【_write函数中的坏味道】
在_write函数和_setFileName函数之间有重复代码
个人觉得可以将此提取出来。

7、【caching参数的必要性】
此参数控制全局的缓存的打开与关闭,在调试程序时十分有用

8、【自动清除旧缓存的控制】
automaticCleaningFactor参数控制是否自动清除旧缓存,
如果此参数的值大于1则会进行自动清除,只是在程序中针对自动清除有一个随机数,
可以理解为 1 / automaticCleaningFactor的机率进行自动清除旧缓存

9、【……】
很轻便的缓存类,如果是简单应用,值得一试!

EOF