更多文章,欢迎关注微信公众号:深夜程猿
什么是LRU算法
LRU算法中文名叫“最近最少使用”,是一种数据缓存淘汰算法,可以实现基于磁盘和内存的缓存淘汰
算法原理
LRU算法根据数据的历史使用记录来进行数据淘汰。LRU算法认为,最近被使用过的数据,那么将来会更多的被使用。LRU实现数据淘汰的原理就是当数据缓存达到预设的最大值时,就会淘汰最久未被使用的数据。
使用场景
LRU算法适用于需要经常访问某些热数据,并且大部分数据都会被重复访问的场景
LRU算法实现方式
基于数组
使用数组实现LRU算法的基本过程如下:
- 数组每一个元素都存有数据和数据标记项。数据标记项是用来识别数据最近被使用的时间。
- 新增一个数据时,会把所有数据的标记项自增,新增的数据标记项设置为0,如果数组中存在该数据,则设置该数据标记项为0即可,不用新增数据。但数组达到最大预设存储空间时,则删除调用数据标记项最大的数据
- 由于删除数据的操作,涉及到数据的迁移,效率比较低。所以,如果存在数据经常没有被缓存命中时,LRU算法很低效
基于单链表
使用单链表实现LRU算法基本过程如下:
- 新增数据时,先判断链表中是否缓存有该数据,如果没有则把该数据放在头结点,如果存在则把该数据移动到头结点
- 新增完数据后,接着判断链表数据是是否超出最大值,是的话就把链表尾部的数据删除掉
- 每次新增一条数据时,都会进行一次链表遍历,最坏情况是链表达到最大值n,需要遍历n次。相对于结点遍历,修改数据结点指针指向的时间可以忽略不计。删除数据时,也会进行一次链表全遍历,最坏情况时遍历n次。所以,寻找一个数据是否在缓存中的最坏情况也是遍历n次。所以,使用单链表实现LRU算法的时间复杂度和链表时间复杂度一样,为O(n)
LRU算法优缺点
- 优点
当存在热点数据时,并且这些大部分数据还是经常被使用的,LRU命中率较高,不需要经常进行数据的添加和删除
- 缺点
如果只有很少的数据被经常使用,LRU算法很低效。因为LRU命中率很低,经常需要淘汰数据。也就是“缓存污染”问题,缓存的数据并没有很大程度上重复使用
LRU-K算法
LRU-K算法是为了解决LRU算法的“缓存污染”问题。可以认为,LRU算法就是LRU-1算法。LRU-K算法目的就是把LRU算法的“最近一次被使用”赋能为“最近K次被使用”。
LRU-K算法原理
LRU-K算法相比于LRU(LRU-1)算法,LRU-K算法一开始不会真正缓存数据,只有数据被使用过了K次才会放入缓存之中。那么,在数据没有被真正缓存之前,数据放在哪里的呢?如何记录使用次数的呢?LRU-K算法会多维护一个队列,用于保存数据的使用记录。但队列中的数据使用达到K次就取出来放进缓存。淘汰缓存数据和LRU(LRU-1)原理一样,第K次使用时间最早的先淘汰。
双队列模式LRU
双队列LRU算法,使用FIFO队列和LRU队列缓存数据。和LRU-K不同的是,双队列LRU算法两个队列都缓存数据,LRU-K算法只使用一个缓存队列缓存数据,一个队列记录数据使用情况
多队列模式LRU
多队列模式LRU的原理是使用多个队列,按照数据不同的使用频率来缓存数据,也就是多优先级缓存。命中的数据会逐渐从低优先级队列缓存到高优先级队列。高优先级队列的数据会逐渐从淘汰到低优先级队列,最后真正被淘汰