主要的内容是计算机组成原理里面的缓存的相关知识。
一个情况是,随着时间的推移设备逐渐发展,CPU的数据处理速度是超过内存数据的访问速度的,这样的话会出现CPU处理完当前数据“无事可做”的情况,而内存的访问速度越快,内存的单位价格越高,为了解决数据访问速度相比处理速度“脱节”的问题,现代的CPU中引入了高速缓存的机制,通过引入多级小容量、速度快的高速缓存,与大容量,速度相对较慢的内存之间形成了类似“阶梯”的关系。通过某些算法可以预先将可能访问的内容从内存先读取到高速缓存中,CPU优先读取高速缓存中的内容,这里有一个词汇来表示读取到缓存中的数据,即所谓的“命中”,而当出现所谓未命中的情况之时,CPU才会直接读取内存中的内容,同时会将数据写入高速缓存,因为时间局部性原理,访问过的数据有很大可能会被再次访问。
在实际的结构上和应用程序->Redis缓存->数据库类似。
从上面的描述中可以看出,算法处理数据预先从内存读取到高速缓存中的这个过程对提高CPU读取数据的命中率,从而提高数据的访问速度是十分重要的,以下记录一下几种相关的算法。
LRU(最近最少使用):如果数据最近被访问过,将来被访问到的几率也更高。
LFU(最不经常使用):一个数据最近一段时间使用次数很少,在将来一段时间内被使用的可能性也很小。
FIFO(先进先出):数据最先进入缓存中,则应该最早被淘汰掉。
浏览器的缓存策略使用的就是LRU。简单来说,将新数据和最近访问的数据优先级提前,当缓存满时将优先级低的数据释放掉。
LFU和LRU的区别是,LFU是从数据的访问次数上来淘汰数据,LRU是从最近一次访问数据的时间间隔上来淘汰数据。
Redis缓存淘汰和对键的过期删除策略:前一个是内存使用超过一定值时候使用的淘汰策略,后者是通过定期删除和惰性删除两者结合进行内存淘汰。key设置过期时间的情况下,每次访问都会检测是否过期,过期则删除,但有一些键只访问一次所以需要主动删除,默认情况下Redis每一秒会在设置过期时间的键集合中检测十次,每次检测20个键,过期则删除,维持过期键不超过键集合的四分之一。
Redis使用24位时间戳的机制来实现LRU,使用16位时间戳加8位计数器来实现LFU,计数器使用了算法维持计数器的增长速度。新加入的数据是不会直接把计数器设置位0的,防止因为访问频率过低被删除。
CPU如何知道访问的数据在缓存中的位置
直接映射Cache:采用取模的方法来讲内存块的地址映射到缓存中对应的块,取N个缓存块对应的M个内存块中的数据,可以取二进制M的低N位来对应到缓存块的地址。使用在缓存块中存储组标记来确定对应的确定内存块,简单地就是存储上面的低N位地址外剩余的地址位。
组标记+数据+有效位(当有效位为0,直接访问内存重新加载数据)
索引(低位)、有效位、组标记(高位),由此确定数据块,从偏移量确定希望读取到的字。