浅析LRU算法

例:

用户信息存在于数据库里,但是由于我们对用户系统的性能要求比较高,显然不能每一次请求都去数据库。所以可以在内存中创建一个哈希表作为缓存,每次查找一个用户的时候现在哈希表中查询,以此提高性能。

但是当用户数据超过一定的数值时,会发生内存溢出,造成服务器宕机。

解决方法:

LRU全称 Least Recently Used ,也就是最近最少使用的意思,是一种内存管理算法,最早应用于Linux操作西永。

LRU算法基于一种假设:长期不被使用的数据,在未来被用到的几率不大。因此,当数据所占内存达到一定阈值时,我们要移除掉最近最少被使用的数据。

在LRU算法中,使用了一种有趣的数据结构,这种数据结构叫做哈希链表。

什么是哈希链表呢?

我们都知道,哈希链表是由若干个Key-value所组成,在逻辑上,这些Key-Value是无所谓排列顺序的,谁先谁后都一样。

在哈希链表中,这些Key-Value不再是彼此无关的存在,而是被一个链条串了起来,每一个Key-Value都具有它的前驱Key-Value、后继Key-Value,就像双向链表中的节点一样。这样一来,原本无序的哈希表拥有了固定的排列顺序。

依靠哈希链表的有序性,我们可以把Key-Value按照最后的使用时间来排序。

示例代码:

``

private  Node head;
private  Node end;
//缓存存储上限 
private  int limit;
private  HashMap<String, Node>  hashMap;
public  LRUCache(int limit){this.limit=limit;hashMap=new HashMap<String, Node>();}
public  String get(String key){Node node=hashMap.get(key);
        if(node==null){return null;}
        refreshNode(node);return node.value;}
public  void put(String key,String value){Node node=hashMap.get(key);
        if(node==null){
        //如果key不存在,插入key-value         
        if(hashMap.size()>=limit){String oldKey=removeNode(head);
        hashMap.remove(oldKey);}
        node=new Node(key,value);
        addNode(node);
        hashMap.put(key,node);}else{        //如果key存在,刷新key-value      
        node.value=value;refreshNode(node);}}
public  void remove(String key){
        Node node=hashMap.get(key);
        removeNode(node);
        hashMap.remove(key);}
/**
 * 刷新被访问的节点位置  * @param  node 被访问的节点
 */
private  void refreshNode(Node node){
        //如果访问的是尾节点,无需移动节点     if  (node ==  end )  {        return ;     }  
        //移除节点    
        removeNode(node);
//重新插入节点     addNode ( node ); }   
/**  * 删除节点  * @param  node 要删除的节点  */
private  String removeNode(Node node){
        if(node==end){
        //移除尾节点       
        end=end.pre;}else if(node==head){
        //移除头节点         head = head . next ;     } else  {      
        //移除中间节点         node . pre . next  = node . next ;         node . next . pre = node . pre ;     }   
        return node.key;}
/**  * 尾部插入节点  * @param  node 要插入的节点  */
private  void addNode(Node node){
        if(end!=null){
        end.next=node;
        node.pre=end;
        node.next=null;}
        end=node;
        if(head==null){
        head=node;
        }}

class Node {
    Node(String key, String value) {
        this.key = key;
        this.value = value;
    }

    public Node pre;
    public Node next;
    public String key;
    public String value;
}

    public static void main(String[] args) {
        LRUCache lruCache = new LRUCache(5);
        lruCache.put("001", "用户1信息");
        lruCache.put("002", "用户1信息");
        lruCache.put("003", "用户1信息");
        lruCache.put("004", "用户1信息");
        lruCache.put("005", "用户1信息");
        lruCache.get("002");
        lruCache.put("004", "用户2信息更新");
        lruCache.put("006", "用户6信息");
        System.out.println(lruCache.get("001"));
        System.out.println(lruCache.get("006"));
    }

以上例代码非线程安全,如有需求,需要加上synchronized修饰符

对于刚才这种类似的需求也可以使用缓存数据库redis来实现,Redis底层也实现了类似于LRU的回收算法。

FIFO算法:

先进先出算法:即FIFO,通过缓存中的块进入队列的先后顺序进行淘汰和替换,先进入缓存的数据块最先被替换。

随机替换算法:

随机替换算法:顾名思义,就是通过随机获得一个需要被替换的块号,并用新的数据替换该块。

LFU算法:

最不经常使用算法:即LFU,这个算法需要记录每一个缓存块被访问的频率,每一次替换都从最低访问频率的数据块开始。

MRU算法:

最近最常使用算法,即MRU,这个算法会最先移除最近最常使用的数据块。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FIFO算法LRU算法都是为了解决缓存淘汰问题而设计的。FIFO算法是一种按照元素插入顺序排序的数据结构,元素在数据结构中按照先进先出的顺序进行存储和访问。在实现缓存时,可以根据实际情况选择使用FIFO算法LRU算法,以达到最佳的缓存淘汰效果。 LRU(Least Recently Used)算法是一种常见的缓存淘汰算法,它的基本思想是“最近最少使用”。在缓存中,最近使用的数据会被优先淘汰,而最近未使用的数据则需要被淘汰以腾出缓存空间。为了实现这一功能,LRU算法通过定期淘汰最近最少使用的数据来保持缓存的最佳状态。LRU算法的核心思想是使用一个缓存数组,数组中的每个元素都存储了一个键值对。每个键值对表示缓存中的一个数据项,包含数据项的键和值。 FIFO算法LRU算法的区别在于,FIFO算法是按照元素插入顺序排序的,而LRU算法是按照元素最近使用的时间排序的。因此,当缓存中的数据项被频繁访问时,LRU算法的效果会更好,因为它会优先保留最近使用的数据项,而FIFO算法则无法做到这一点。 以下是一个使用Python实现LRU算法的例子: ```python from collections import OrderedDict class LRUCache: def __init__(self, capacity: int): self.cache = OrderedDict() self.capacity = capacity def get(self, key: int) -> int: if key not in self.cache: return -1 self.cache.move_to_end(key) return self.cache[key] def put(self, key: int, value: int) -> None: if key in self.cache: self.cache.move_to_end(key) self.cache[key] = value if len(self.cache) > self.capacity: self.cache.popitem(last=False) ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值