前言:
对于工作经验仅仅只有一年的我来说, 写这篇文章有些吃力,并且感觉有些理解还不够透彻,但是还是铆足了劲想啃啃缓存这块硬骨头。缓存是性能优化的一个必经之路,可以说用好了缓存,性能优化的路就走完一半了。
一、系统缓存
在知乎上找到这样一篇讲计算机缓存的文章计算机缓存Cache以及Cache Line详解
存储器是分层次的,离CPU越近的存储器,速度越快,每字节的成本越高,同时容量也因此越小。寄存器速度最快,离CPU最近,成本最高,所以个数容量有限,其次是高速缓存(缓存也是分级,有L1,L2等缓存),再次是主存(普通内存),再次是本地磁盘。
在计算机中, CPU所需要的数据全部都来自于内存, 不管是在内存本身的数据还是在磁盘上的数据还是存在网络上的数据, 最终终究是会读取到内存中去, 然后CPU才能够得到数据并作出相应的反应。而在CPU和内存之间就存在者另一种一种物理硬件就是缓存,缓存中往往存着CPU正在执行的一些指令,这样就会减少CPU对内存访问的次数,从而加快CPU的执行效率。在这里所讲的缓存是计算机设备的缓存。
二、Web缓存
在应用的客户端或服务端缓存并不会有一个真正的物理设备来提高效率, 而是通过内存或本地磁盘来进行存储缓存数据来减少双端交互,减少被请求端的查询操作,以此来减少被请求端的计算次数,减轻被请求端的压力。
按照应用分的话,Web缓存大致可以分为:
- 数据库缓存;
- 服务器端缓存(代理服务器缓存、CDN 缓存);
- 浏览器缓存。
浏览器缓存也包含很多内容: HTTP 缓存、indexDB、cookie、localstorage 等等。
按照应用场景进行划分, 还可以分为:
- 本地缓存;
- 分布式缓存。
三、缓存的特征
- 命中率
命中率=返回正确结果数/请求缓存次数,命中率问题是缓存中的一个非常重要的问题,它是衡量缓存有效性的重要指标。命中率越高,表明缓存的使用率越高。 - 最大元素
缓存中可以存放的最大元素的数量,一旦缓存中元素数量超过这个值(或者缓存数据所占空间超过其最大支持空间),那么将会触发缓存启动清空策略根据不同的场景合理的设置最大元素值往往可以一定程度上提高缓存的命中率,从而更有效的时候缓存。 -
清空策略
如上描述,缓存的存储空间有限制,当缓存空间被用满时,如何保证在稳定服务的同时有效提升命中率?这就由缓存清空策略来处理,设计适合自身数据特征的清空策略能有效提升命中率。常见的一般策略有:- FIFO(first in first out)
先进先出策略,最先进入缓存的数据在缓存空间不够的情况下(超出最大元素限制)会被优先被清除掉,以腾出新的空间接受新的数据。策略算法主要比较缓存元素的创建时间。在数据实效性要求场景下可选择该类策略,优先保障最新数据可用。 - LFU(less frequently used)
最少使用策略,无论是否过期,根据元素的被使用次数判断,清除使用次数较少的元素释放空间。策略算法主要比较元素的hitCount(命中次数)。在保证高频数据有效性场景下,可选择这类策略。 - LRU(least recently used)
最近最少使用策略,无论是否过期,根据元素最后一次被使用的时间戳,清除最远使用时间戳的元素释放空间。策略算法主要比较元素最近一次被get使用时间。在热点数据场景下较适用,优先保证热点数据的有效性。 - 其他(除此之外,还有一些简单策略比如)
根据过期时间判断,清理过期时间最长的元素;
根据过期时间判断,清理最近要过期的元素;
随机清理;
根据关键字(或元素内容)长短清理等。
虽然从硬件介质上来看,无非就是内存和硬盘两种,但从技术上,可以分成内存、硬盘文件、数据库。
- FIFO(first in first out)
-
存储位置
- 内存:将缓存存储于内存中是最快的选择,无需额外的I/O开销,但是内存的缺点是没有持久化落地物理磁盘,一旦应用异常break down而重新启动,数据很难或者无法复原。
- 硬盘:一般来说,很多缓存框架会结合使用内存和硬盘,在内存分配空间满了或是在异常的情况下,可以被动或主动的将内存空间数据持久化到硬盘中,达到释放空间或备份数据的目的。
- 数据库:前面有提到,增加缓存的策略的目的之一就是为了减少数据库的I/O压力。现在使用数据库做缓存介质是不是又回到了老问题上了?其实,数据库也有很多种类型,像那些不支持SQL,只是简单的key-value存储结构的特殊数据库(如BerkeleyDB和Redis),响应速度和吞吐量都远远高于我们常用的关系型数据库等。
下一节将具体了解一下浏览器缓存。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。