LRU算法(php实现)

1.原理

LRU(least recently used, 最近最少使用),LRU算法的设计原则是:

如果一个 数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。

(最开始了解这个算法的时候一直不明白为什么要淘汰最近的数据,而不是淘汰最远的数据,看到设计原则的时候才恍然大悟)
  值得一提的是redis采用拉链法解决哈希碰撞,采用的头插法将最新的数据存储到链表的头部,其设计思想也是

最先存储的数据也是最快被使用到的,从而提高数据的查找效率

2.实现

可能大多数人会想到:用一个数组来存储数据,给每一个数据项标记一个访问的时间戳;每次插入新数据项的时候,将已存在的数据项的时间戳自增,并将新数据的时间戳置为0;每次访问数据项的时候,将被访问的数据项的时间戳置为0
   当数组空间已满的时候,将时间戳最大的数据项淘汰。这种实现的方式很简单,但是有个问题,需要不挺的维护数据项的访问时间戳,另外在插入,删除以及访问数据时,时间复杂的都是O(n)
我们需要关注淘汰算法的读性能和写性能,理想的LRU应该可以在O(1)的时间内读取一条数据或更新一条数据,也就是说读写的时间复杂度都是O(1)
所以最好的实现方式就是利用链表和HashTable

HashTable主要用于查找数据,保证通过key访问数据的时间复杂度为O(1)。而用链表用来保存缓存数据。

算法的实现过程如下
算法实现
步骤:
1。新数据插入到链表头部;(O(1))
2。每当缓存命中即缓存数据被访问的时候,将数据移到链表头部;(不需要移动大量数据,只需修改链表指针O(1))
3。当链表满的时候,将链表尾部的数据清除;(O(1))

3.php实现

php代码转自github:php-lruchache

4.例题

题目是某缓存系统采用LRU算法,假定缓存容量为4,并且初始为空,那么在顺序访问以下数据项的时候,
1,5,1,3,5,2,4,1,2
出现缓存直接命中的次数是(3)次,最后缓存中即将准备淘汰的数据项是(5)。

访问过程如下:

get memory hit
1 1
5 5 1
1 1 5 true
3 3 1 5
5 5 3 1 true
2 2 5 3 1
4 4 2 5 3 (尾部的1淘汰)
1 1 4 2 5 (尾部的3淘汰)
2 2 1 4 5 true

结论:
缓存命中3
5在链表尾部,缓存已满,所以即将淘汰的是5

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章