数据库专题(四)
——各类缓存技术
(原创内容,转载请注明来源,谢谢)
一、概述
缓存(Cache)技术原指高速数据,当CPU处理数据的时候,会先去缓存里面找,有的话就直接返回,不用再去RAM取数据。但是现在缓存已经不仅指cpu的操作了,而在程序中更多的是指内存和硬盘之间的缓存。凡是速度差距较大的两者,有介于中间的速度差异的结构,均可以称为用cache。速度排序,CPU>内存>硬盘,因此cpu到内存、内存到硬盘都有缓存。
1、优势
缓存利用相对高速的速度减少介质交互、低速操作等,例如减少网络I/O、减少硬盘I/O,达到加快速度的目的。从浏览器输入连接到最后的展示,几乎每一步都可以用缓存。
web上的缓存主要有如下:(PHP)
1)底层有CPU缓存、磁盘文件系统缓存;
2)应用层有Zend虚拟机变量缓存、APC与eAccelerate等基于Opcode字节码的缓存;
3)数据库层有表缓存、查询缓存、Thread Cache;
4)Servlet容器层有Apache缓存;
5)Web Cache层有Squid、Vanish缓存,应用程序代码级别Smarty文件缓存、基于HTTP协议和浏览器自身的缓存。
6)NoSQL,即Not OnlySQL,包括Memcached、Redis、MongoDB等,主要都是存储在内存中,减少硬盘的交互。
缓存主要存于内存和硬盘,文件缓存主要存在硬盘,高速存储主要存于内存中,但是当内存满时或者阶段性dump的时候,也会选择将数据持久化到硬盘,防止数据丢失。
缓存有三大重要因素:命中率、缓存更新策略、缓存最大数据量。
2、缓存命中率
通过缓存命中率,可以衡量缓存设置的好坏,命中率越高说明缓存的机制越好。
Mysql的Query Cache用于缓存客户端提交给mysql的select语句与语句的结果集,其将select语句和语句的结果hash映射后存入内存。其中有很多globalstatus记录query cache的当前状态,包括空闲query cache内存总量、命中次数、没有被缓存的sql的数目、当前缓存的总量等。mysql提供命令show global status查看当前的global status。
mysql只会存储查询语句的缓存,不会存储插入、更新、删除、存储过程(包括存储过程内的select)、show命令。
缓存命中率=当前缓存的总量/总查询量。通常值在85%以上算比较高的。当需要频繁更新表格时,query cache大量会失效,此时query cache不仅不能提高速度,反而会有负面影响。
3、缓存更新策略
querycache缓存更新策略是通过设置所用的总内存,当内存塞满,就会剔除老的query cache。另外,为了保证内容的一致性,当query cache所记录的表格的内容有发生新增、修改、删除,则会包含该表格的query cache失效。
当缓存的空间满的情况下,缓存的更新包含几种:
1)FIFO,最先记录缓存的最先被清理。
2)LFU,最少使用的元素被清理,即querycache的Qcache_hits参数。
3)LRU,最近最少使用的元素被清理。
mysql使用FIFO的方式清除最早的数据。
4、缓存最大数据量
缓存最大数据量指缓存中能处理元素的最大个数或使用的最大存储空间。query cache通过query_cache_size确定,而基于key-value的如memcached等缓存,最大数据量由操作系统决定,默认64MB。
超过缓存最大数据量,有可能进行几种处理:
1)停止缓存,并清空缓存。
2)拒绝写入,不更新缓存。
3)根据缓存更新策略清除旧数据。
4)根据缓存更新策略,备份淘汰的数据后,腾出新空间。
通常用3、4两种方式。
二、文件缓存
文件缓存是把数据存在硬盘的文件中,硬盘的速度虽然比内存慢,但是也有其优点,主要有:容量大、稳定、扩展容易。web中主要是模板引擎和配置文件应用文件缓存。
1、文件缓存机制
模板引擎使用文件缓存机制,是将动态的PHP代码编译成静态的HTML,下次读取不用编译,可以直接读取静态文件,即实现页面的静态化。主要步骤如下:
1)根据配置文件判断是否要缓存,如果不用缓存则直接include php文件,否则进入下一步。
2)判断对应的静态文件,如果此处没有缓存文件,则编译,并将内容保存为静态html,否则进入下一步。
3)根据配置文件设定的过期时间,判断静态文件是否过期,未过期则读取,否则重新编译。
通常,耗费数据库资源较大而改动量又较少的情况下,会将数据进行存储,例如无限分类应用,其分类改动的较少时,就可以使用此方式。
2、常用文件缓存插件
Secache,不需要安装任何扩展,直接引入就可以使用,纯PHP开发,其采用key-value的方式进行存储。
三、Opcode缓存
PHP和Java的明显不同之处在于,PHP程序运行完后,马上释放所有内存,所有程序中的变量都销毁,计算机的内存中几乎不存在PHP代码的数据。
优点是避免内存泄漏,内存回收机制简单,避免因为程序导致服务器被影响;缺点是无法复用已有的数据,每次请求都要重新翻译、执行,导致速度可能会偏慢。
PHP在执行时会被转化成Opcode(操作码),因此可以在转化后进行缓存,省去下次执行PHP时再次语法编译和检查,可以直接解释Opcode。
1、eAccelerator
该工具能起到常驻内存的作用。下载后将dll文件放于PHP的ext目录,并修改php.ini,加入一些配置。当再次请求时,会直接取出Opcode,由Zend虚拟机直接执行,节省语法解析的消耗。经过配置文件的配置,会将Opcode的缓存保存在文件中。
另外,eaccelerator具有共享变量功能,即允许用户调用API实现读取、存入的操作,其操作类似redis、memcached。命令如下:
1)eaccelerator_put($key,$value, $ttl=0),将$value存在共享内存中,时间是ttl秒,用key可以取出结果。
2)eaccelerator_get($key),获取缓存值。
2、VLD扩展
安装VLD扩展后,可以监测Opcode的缓存情况。另外在eaccelerator官网可以下载到control.php文件,可以查看到允许结果的web页面展示。
四、客户端缓存
对于web应用,客户端缓存即web缓存。web缓存是由浏览器来实现的,即浏览器在计算机上开辟一个硬盘空间,用于存储已经看过的副本,当用户后退、或者点击已经点过的连接,则会直接返回结果,图片等加载较慢的文件实现快速加载。
1、客户端缓存规则
如果相应头信息告诉缓存不要缓存,或请求头信息包括认证或者安全加密信息,或回应中不存在校验器ETag或者LastModified信息,则不会缓存。
缓存的内容包括:完整的过期时间和寿命控制头,保证内容够新;浏览器、代理服务器已经缓存过的副本,则会直接输出,不会向源服务器发送请求。如果副本太久,则会根据服务器的策略,判断是否要更新缓存。
2、HTTP协议中使用缓存
当输入URL,浏览器没有缓存时,会向服务器发送请求,服务器处理后返回的结果带状态码200;第二次再发送请求时,如果没有变化,则服务器会发送304头信息,标记没有更新,则浏览器直接从本地的缓存取数据。头信息中几个重要的标识如下:
1)Expires
过期时间是HTTP控制缓存的方法,其告诉缓存器可以缓存多久,在过期时限内的请求都会直接返回缓存的结果,超过时间则会向服务器发送请求判断是否有被修改过。该设置主要应对静态图片,这些修改的很少,通常可以设置一个很长的过期时间,网站会变得很快。时间的基准是GMT(格林威治时间)。
2)Cache-Control
该响应包括缓存过期时间、是否强制每次直接发送请求、是否允许缓存、缓存保鲜时间、文档最后修改时间等配置。当浏览器第二次发送请求时,会发送If-Modified-Since,询问服务器是否修改过内容,但是如果时间比当前时间晚,会被认为是非法请求。
3)ETag
此为服务器响应请求的URL标记副本的变化,每次的副本此标签都不同,用于和服务器进行比对。
3、策略
1)不常更新的图片或页面用缓存,可以将Cache-Control的max-age属性设置的足够长。
2)定期更新的内容设置一个缓存服务器可识别的max-age属性或过期时间。
3)POST基本不会被缓存,因此当查询时尽量用get。
4、PHP调用缓存
header(‘Cache-control:max-age=3600,must-revalidate’);//1小时
header(‘Last-Modified:’.gmdate(‘D,d M Y H:i:s’).’GMT’);
header(‘Expires:‘.gmdate(‘D, d M Y H:i:s’, time()+’86400’).’GMT’);
…….//具体代码
上述命令执行一次后,刷新或者输入url都不会重新请求,即使改变具体代码也不会有变化。仅缓存到期、缓存被清除、强制刷新(通常是Ctrl+F5),会重新读取文件。
5、避免文件被缓存
js等文件,如果为了避免被缓存,可以给js的文件名后面加上版本号,这样每次更新js的时候,改变版本号,浏览器因为识别到不同的js,则会去服务器请求数据。
五、web服务器缓存
1、Apache缓存
Apache的mod_expires和mod_headers模块,可以启用缓存。如果开启这两个模块,则可以在.htaccess文件或者服务器的access.conf文件,通过mod_expires设置副本过期时间。
设置expire后,系统会自动输出Cache-Control的max-age信息。
2、Nginx缓存
Nginx可以实现传统的缓存,如基于Squid,也可以基于proxy_cache的缓存。
proxy_cache配置结合server配置的缓存如下:
proxy_cache/cachepath levels=1:2 keys_zone=NAME:10m inactive=5m max_size=2m clean_time=1m;
location/ {
proxy_psshttp://xxxx.com
proxy_cacheNAME;
proxy_cache_valid200 302 1h;
proxy_cache_valid301 2h;
proxy_cache_validany 1m;
}
——written by linhxx 2017.08.08