缓存淘汰算法LRU

基本概念

Least Recently Used,即最近最少使用,是内存管理的一种页面置换算法。算法的核心是:如果一个数据在最近一段时间内没有被访问到,那么它在将来被访问的可能性也很小。换言之,当内存达到极限时,应该把内存中最久没有被访问的数据淘汰掉。

一般实现

理论上只需要一个列表,数据被使用时,不在LRU列表中就放到头部,在就提到头部,相应淘汰尾部的数据即可。或者数据使用时记录使用时间戳,每次比对时间戳,最小的淘汰。
使用hashmap可以使时间复杂度由O(n)降低至O(1)。
使用python 双向链表+hashmap

from collections import OrderedDict

class LRUDict(OrderedDict):

   def __init__(self, capacity):
       self.capacity = capacity
       self.items = OrderedDict()

   def __setitem__(self, key, value):
       old_value = self.items.get(key)
       if old_value is not None:
           self.items.pop(key)
           self.items[key] = value
       elif len(self.items) < self.capacity:
           self.items[key] = value
       else:
           self.items.popitem(last=False)
           self.items[key] = value

   def __getitem__(self, key):
       value = self.items.get(key)
       if value is not None:
           self.items.pop(key)
           self.items[key] = value
       return value

   def __repr__(self):
       return repr(self.items)

变种

一种策略不是万能的,不同的场景决定了不同的用法

redis中的LRU

场景

redis占用内存达到极限时,就需要将一部分数据写入磁盘,此时就需要一种策略来决定的是哪一部分写入磁盘。

特点

redis放在内存中,双向链表+hashmap 这样占用比较大的结构比较奢侈。redis需要采用更节省空间的实现方式。

实现

Redis 在实现上引入了一个 LRU 时钟来代替 unix 时间戳,每个对象的每次被访问都会记录下当前服务器的 LRU 时钟,然后用服务器的 LRU 时钟减去对象本身的时钟,得到的就是这个对象没有被访问的时间间隔(也称空闲时间),空闲时间最大的就是需要淘汰的对象。redis则随机选取 若干(server.maxmemory_samples配置) 个 key,然后比较它们的lru访问时间,然后淘汰最近最久没有访问的key。(假设maxmemory_samples为最大即当前key数量,每次比较所有key的LRU访问时间,此时算法由回到了朴素的LRU算法)

innodb中的LRU

特点

sql经常会有全表扫描这样的查询,如果使用朴素LRU算法,缓冲池的页会被经常刷完,起不到缓冲的作用。

实现

加入midpoint,数据进来先加入到midpoint,在根据设置的时间提到LRU列表头。

其他淘汰算法

LFU算法

LFU(Least Frequently Used ,最近最少使用算法)也是一种常见的缓存算法。
顾名思义,LFU算法的思想是:如果一个数据在最近一段时间很少被访问到,那么可以认为在将来它被访问的可能性也很小。因此,当空间满时,最小频率访问的数据最先被淘汰。

算法实现策略:考虑到 LFU 会淘汰访问频率最小的数据,我们需要一种合适的方法按大小顺序维护数据访问的频率。LFU 算法本质上可以看做是一个 top K 问题(K = 1),即选出频率最小的元素,因此我们很容易想到可以用二项堆来选择频率最小的元素,这样的实现比较高效。最终实现策略为小顶堆+哈希表。
redis4.0提供LFU算法。LFU算法如果有数据短时高频访问,则会一直留在内存中

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值