zoukankan      html  css  js  c++  java
  • Java--缓存热点数据,最近最少使用算法

    1、最近最少使用算法LRU (Least recently used,最近最少使用)

    【实现】:最常见的是使用一个链表保存缓存数据

    1、新数据插入到链表头部;

    2、每当缓存命中(即缓存数据被访问),将数据移动到链表头部;

    3、当链表满的时候将链表尾部的数据丢弃;

    【代价】

    命中时需要遍历链表,找到命中的数据块索引,然后需要将数据移到头部。

    【改变】

    基于以上代价,我们将维护的链表改为一个双向链表(即每个节点都有个prev和next),另外需要再多维护一个map,将缓存对象的引用放入map中;

    1、新数据插入链表头部,并且放入map中

    2、每当需要使用缓存时,首先通过key到map中查找,命中缓存后将数据移动到链表头部(这个移动就非常好移动了,只需要把该节点的prev节点的next属性赋值为该节点的next节点,同时把该节点的next节点的prev属性赋值为该节点的prev节点,并且将该节点放入链表头部就可以了)。

    3、当链表满的时候将链表尾部的数据丢弃,并且删除map中对应的数据。

    【结果】

    基于以上改变的LRU算法,完全去除了命中缓存需要遍历链表这个缺点,性能得到了大的提升。

    2、使用redis缓存数据,保证热点数据的缓存用法与原理

    说一点:只要限制了redis占用的内存,redis会根据自身数据淘汰策略,加载热数据到内存。

    【实现】:

    通过redis本身的设置过期时间来实现缓存热点数据

    1、缓存每命中一次,就重新给该数据设置过期时间

    2、那么经常命中的缓存始终不会过期,不会被删除,而非热点数据过期时间一到那么就会被删除掉,保证了redis中始终存在的是热点数据。

    【原理】

    1、原理其实就是Java中延时阻塞队列DelayQueue的原理

    2、当对redis中缓存数据设置过期时间,相当于将缓存数据放入redis中维护的延时阻塞队列DelayQueue。

    3、DelayQueue会对放入的缓存数据根据过期时间进行排序,时间短的在前面,时间长的在队列后面。

    4、会使用一个或者多个线程循环查询DelayQueue,一旦能从DelayQueue获取元素了就说明该缓存数据到期了,就可以取出来并且删除掉了。

    5、当有多个线程都同时查询DelayQueue的时候,只有一个线程能够争取到头元素,其它线程将被阻塞。当头元素被取走以后,会唤醒所有阻塞线程,线程竞争头元素,竞争到头元素的线程会查询头元素的剩余delay时间,并且标记头元素已经被该线程占有,再根据delay时间wait自己,最后获取头元素后唤醒其它阻塞线程。

  • 相关阅读:
    解决MySql报错:1130
    Mac 安装 RabbitMQ 出现的问题
    Java 中的关键字
    ExtJS 去除水印
    MAC VMware fusion 12.1.0 Centos7 网络配置
    Linux常见目录结构
    CentOS 设置网络及安装 ifconfig
    Web项目部署到IIS的方法
    异常处理-System.IO.IOException: 由于远程方已关闭传输流,身份验证失败
    C#委托总结-匿名方法&Lambda表达式
  • 原文地址:https://www.cnblogs.com/eoss/p/6202185.html
Copyright © 2011-2022 走看看