LRU算法用来做数据淘汰的算法,用来淘汰最近最少访问的数据;一般使用链表实现,当一个key被访问时,就将key放在链表头部,当需要淘汰数据时,就将链表末尾的数据淘汰。
redis中的应用
redis中淘汰数据有两个方式:
- 定期删除:redis有后台线程,会定时扫描数据,从中选择应该淘汰的过期数据将其删除。假如每次删除都对所有的key进行一次最近访问时间排序的话,对性能消耗非常大,redis采用的是随机抽样的方式进行删除,例如LRU算法删除,则随机抽取20个key,从中找出最近未访问的key进行删除。这样随机抽取能提高性能,但是不能覆盖到所有的key,会存在一个问题,对于设计了过期时间的数据,理论上来说应该将其删除,但是多次随机抽取均为选中,因此未被淘汰。
- 惰性删除:针对定期删除不能完全淘汰所有应该淘汰的数据的问题,当redis访问了key之后,redis会判断key是否已经过期,如果已经过期就直接删掉。
mysql中的应用
mysql中的buffer pool也是用来加速查询的缓存,当buffer pool的容量被占满时,也需要淘汰数据,其中数据的淘汰也是基于LRU算法的。
所有从磁盘上读取的数据首先都会缓存在buffer pool中。当对存放大量冷数据的表进行查询时,会在短时间内将大量冷数据加载到buffer pool中,如果buffer pool被占满之后就会根据LRU算法淘汰数据,可能就把之间的热点数据淘汰了,从而导致的缓存命中率下降。
为了避免因为冷数据表的查询导致热点数据被淘汰的问题,mysql对LRU算法进行了改进,将buffer pool分成young和old两个区域,所有数据被加载进buffer pool时都是先放在old区,当在old区待足够长的时间或被访问次数达到阈值时数据才会被放到young区。数据淘汰也是优先从old区淘汰。这样就能避免大量冷数据加载导致的热点数据淘汰问题。