缓存命中率
缓存命中率
当程序需要第k+1层中的某个数据时d,会首先在它的缓存k层中寻找。如果数据刚好在k层中,就称为缓存命中(cache hit)。
终端用户访问加速节点时,如果该节点有缓存住了要被访问的数据时就叫做命中,如果没有的话需要回原服务器取,就是没有命中。
取数据的过程与用户访问是同步进行的,所以即使是重新取的新数据,用户也不会感觉到有延时。
命中率=命中数/(命中数+没有命中数)
缓存命中率是判断加速效果好坏的重要因素之一。
缓存的命中率取决于很多的因素:
[](javascript:void(0);)
应用场景
看访问的频度,一个极少被访问到的缓存等于没有什么效果。一般来说,互联网网站是非常适合缓存应用的场景。
缓存的粒度
缓存的粒度越小,命中率就越高,对象缓存是目前缓存粒度最小的,因此被命中的几率更高。 举个例子:你访问当前这个页面,浏览帖子,那么对于ORM来说,需要发送n条SQL,取各自帖子user的对象。很显然,如果这个user在其他帖子里面也跟贴了,那么在访问那个帖子的时候,就可以直接从缓存里面取这个user对象了。
架构的设计
架构的设计对于缓存命中率也有至关重要的影响。 例如你应该如何去尽量避免缓存失效的问题,如何尽量提供频繁访问数据的缓存问题,这些都是考验架构师水平的地方。 再举个例子来说,对于论坛,需要记录每个topic的浏览次数,所以每次有人访问这个topic,那么topic表就要update一次,这意味着什么呢?对于topic的对象缓存是无效的,每次访问都要更新缓存。那么可以想一些办法,例如增加一个中间变量记录点击次数,每累计一定的点击,才更新一次数据库,从而减低缓存失效的频率。
缓存的容量和缓存的有效期
缓存太小,造成频繁的LRU,也会降低命中率,缓存的有效期太短也会造成缓存命中率下降。
所以缓存命中率问题不能一概而论,一定说命中率很低或者命中率很高。但是如果你对于缓存的掌握很精通,有意识的去调整应用的架构,去分解缓存的粒度,总是会带来很高的命中率的。
[](javascript:void(0);)
缓存命中和局部性
为什么局部性好的程序能有更好的性能
利用时间局部性:由于时间局部性,同一个数据对象会多次被使用。一旦一个数据对象从k+1层进入到k层的缓存中,就希望它多次被引用。这样能节省很多访问造成的时间开支。
利用空间局部性:假设缓存k能存n个数据块。在对数组访问的时候,由于数组是连续存放的,对第一个元素访问的时候,会把第一个元素后面的一共n个元素(缓存k有n个数据块)拷贝到缓存k中,这样在对第二个元素到第n个元素的访问时就可以直接从缓存里获取,从而提高性能。
同理,访问第n个元素的时候 ,n不在缓存中,缓存管理器会把从n到2n的元素拷贝到缓存中,对它们的访问就可以直接在缓存中进行。
通过空间局部性,我们希望对后面对缓存中其他对象的访问能补偿不命中后拷贝这些块的时间花费。