缓存详解 [TOC] #### 1. 认识缓存 缓存(Cache)的原意是指一种应用高速率数据交换的存储器。在CPU处理数据时先到缓存中去寻找,如果数据已经因之前的操作而被暂存其中,就不需要再从随机读取存储器(RAM)中寻找。 现在缓存的概念已被扩充,不仅在CPU和内存之间有缓存,内存和硬盘之间也有缓存(磁盘高速缓存)。**凡是两种速度相差较大的两种介质之间,用于协调两者数据传输速度差异的结构,均可称为缓存(Cache)。** #### 2. 为什么使用缓存 随着业务的复杂度和并发量的增加,应用服务器和数据库服务器的压力也逐渐变大,那么如何在有限的硬件资源中尽可能大的提高效率呢? 一个办法:**减少计算量,减少请求流程(网络I/O和硬盘I/O)**,这时缓存就可以大展伸手了。 **缓存的基本原理就是打破标准流程,在标准流程中的任何环节都可以被切断。**请求可以从缓存中读取到需要的数据然后返回给用户,这样可以节省时间、提高响应速度、减少硬件资源消耗,可以让有限的硬件资源服务更多的用户。 在web世界,理论上每一层都可以被缓存,以PHP为例: |层级|缓存| |:--|:--| |底层|CPU缓存、硬盘文件缓存| |应用层|Zend虚拟机变量缓存、Redis等key-value缓存、Opcode字节码缓存| |数据库层|Table Cache、Tread Cache、Query Cache| |Servlet容器层|Apache缓存、Nginx缓存等| |WebCache层|Squid、Varnish等| |代码层|文件缓存| 缓存的存储位置无非是硬盘和内存两个地方。存储在硬盘中的就是文件缓存,一般来说需要高速读取的数据要存放在内存中。缓存组件大多都是结合内存和硬盘的,例如如果内存满了之后会将部分数据持久化到硬盘中,或者缓存组件会定期将内存中的数据写入到硬盘中,防止数据丢失。 #### 3. 缓存的三要素 缓存中有三大要素:命中率、缓存更新策略、缓存最大数据量。 ##### 3.1 命中率 **通常来讲命中率是衡量一个缓存机制的好坏和效率的标准。** **命中率是指请求缓存的次数和缓存正确结果的次数的比例。**比例越高证明这个缓存的使用率越高。 在不同的缓存应用中命中率也各不相同,例如Query Cache的缓存在经过一段时间的运行和积累之后,通常可以达到98%以上的命中率。而在其他应用中命中率能达到85%就非常不错了,98%是理想状态。这根缓存机制的实现有很大关系,**缓存机制越复杂,命中率就越低**。 ##### 3.2 更新策略 一般情况下,缓存更新策略分为以下几种: ###### 3.2.1 FIFO First In First Out。 最先存储的数据在内存不足或达到限制时最先被清理。 ###### 3.2.2 LFU Less Frequently Used。最少使用的缓存被最先清理。这需要缓存中存在hit属性,在内存不足或达到限制时,hit值最小的会被最先清理。 ###### 3.2.3 LRU Least Recently Used。最近最少使用的最先被清理。缓存中会存在一个时间戳,在内存不足或达到限制时,缓存时间戳离当前时间最远的会被清理。 ##### 3.3 最大数据量 缓存最大数据量是指对缓存中元素的最大存储个数或数据的最大存储空间进行限定。一般缓存应用都会默认对其做出限定,也可以由用户指定或者由操作系统分配。 当缓存的数据量达到限定值后缓存应用会做出处理,一般处理方式为以下几种: 1. 停止缓存服务,并清空所有缓存数据。 2. 拒绝写入,不在对缓存数据进行更新。 3. 根据缓存更新策略清除旧数据。 4. 在3的基础上将被清除的数据备份。 在实际应用中以3和4最为常见。 #### 4. 文件缓存 文件缓存即将要保存的数据存储在硬盘中。与内存相比硬盘的存取效率要低很多,但文件缓存依然被大量使用的原因有以下几点: 1. 磁盘容量大,可以存储足够多的的数据。常规的硬盘已进入TB级别,而内存还在GB级别。另外相比较于内存,硬盘的成本也要低很多。 2. 磁盘更加稳定和可靠,即使断电后数据也不会丢失。 3. 随着技术的发展,目前已经出现了固态硬盘,使其存取效率大幅度提高,可以达到500MB/s。 4. 扩展方便。可以使用磁盘阵列、分布式处理等大规模的存储和管理。 #### 5. Opcode缓存 一个PHP程序在执行完毕后会马上被释放,基本上所有的数据都在此时被销毁(仅有极少数数据被缓存),也就是说此时计算机内存中基本不存在这个PHP代码的数据。这和常驻内存的语言如JAVA有显著区别。这种缓存机制存在以下优缺点: 优点:有效避免内存泄漏,回收机制更简单,避免因为一个程序导致服务求崩溃的情况。 缺点:无法复用已有数据,每个PHP请求都要重复执行:请求>编译>执行的过程。重复过多。 Opcode就是将PHP虚拟机编译得到的中间码存储起来,可以是硬盘或者内存。下次请求该页面时直接运行这些中间码即可,无需重复过多的步骤。这样省去了语法器的检查和编译过程,加快了PHP的运行速度,减轻了服务器的负荷。 2019-04-06 PHP核心技术与最佳实践 展开评论