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自己,最后获取头元素后唤醒其它阻塞线程。

Java--缓存热点数据,最近最少使用算法的更多相关文章

  1. 在这个应用中,我使用了 MQ 来处理异步流程、Redis 缓存热点数据、MySQL 持久化数据,还有就是在系统中调用另外一个业务系统的接口,对我的应用来说这些都是属于 RPC 调用,而 MQ、MySQL 持久化的数据也会存在于一个分布式文件系统中,他们之间的调用也是需要用 RPC 来完成数据交互的。

    在这个应用中,我使用了 MQ 来处理异步流程.Redis 缓存热点数据.MySQL 持久化数据,还有就是在系统中调用另外一个业务系统的接口,对我的应用来说这些都是属于 RPC 调用,而 MQ.MySQ ...

  2. 缓存雪崩、穿透如何解决,如何确保Redis只缓存热点数据?

    缓存雪崩如何解决? 缓存穿透如何解决? 如何确保Redis缓存的都是热点数据? 如何更新缓存数据? 如何处理请求倾斜? 实际业务场景下,如何选择缓存数据结构 缓存雪崩 缓存雪崩简单说就是所有请求都从缓 ...

  3. 使用guava cache在本地缓存热点数据

    某些热点数据在短时间内可能会被成千上万次访问,所以除了放在redis之外,还可以放在本地内存,也就是JVM的内存中. 我们可以使用google的guava cache组件实现本地缓存,之所以选择gua ...

  4. java缓存算法【转】

    http://my.oschina.net/u/866190/blog/188712 提到缓存,不得不提就是缓存算法(淘汰算法),常见算法有LRU.LFU和FIFO等算法,每种算法各有各的优势和缺点及 ...

  5. LeetCode之LRU Cache 最近最少使用算法 缓存设计

    设计并实现最近最久未使用(Least Recently Used)缓存. 题目描述: Design and implement a data structure for Least Recently ...

  6. java之ibatis数据缓存

    使用IBatis作数据缓存 1.SqlMapConfig.xml中<settingscacheModelsEnabled="true" //设置为trueenhancemen ...

  7. 简单的java缓存实现

    扫扫关注"茶爸爸"微信公众号 坚持最初的执着,从不曾有半点懈怠,为优秀而努力,为证明自己而活. 提到缓存,不得不提就是缓存算法(淘汰算法),常见算法有LRU.LFU和FIFO等算法 ...

  8. 【转】简单的java缓存实现

    本文转自 http://my.oschina.net/u/866190/blog/188712 提到缓存,不得不提就是缓存算法(淘汰算法),常见算法有LRU.LFU和FIFO等算法,每种算法各有各的优 ...

  9. 面试题之java缓存总结,从单机缓存到分布式缓存架构

    1.缓存定义 高速数据存储层,提高程序性能 2.为什么要用缓存(读多写少,高并发) 1.提高读取吞吐量 2.提升应用程序性能 3.降低数据库成本 4.减少后端负载 5.消除数据库热点 6.可预测的性能 ...

随机推荐

  1. C#+OpenGL+FreeType显示3D文字(3) - 用PointSprite绘制文字

    C#+OpenGL+FreeType显示3D文字(3) - 用PointSprite绘制文字 上一篇实现了把文字绘制到OpenGL窗口,但实质上只是把含有文字的贴图贴到矩形模型上.本篇我们介绍用Poi ...

  2. hibernate学习笔记之三 持久化的三种状态

    Hibernate持久化对象有3中状态,瞬时对象(transientObjects),持久化对象(persistentObjects),离线对象(detachedObjects) 下图显示持久化三种状 ...

  3. Transactional Replication2:在Subscriber中,主键列是只读的

    在使用Transactional Replication时,Subscriber 被认为是“Read-Only”的 , All data at the Subscriber is “read-only ...

  4. 自制编程语言crowbar(v0.1)构建解析器时分配内存

    crowbar中第一次申请内存是在生成解析器的时候: /* interface.c */CRB_Interpreter *CRB_create_interpreter(void) { MEM_Stor ...

  5. nodejs 使用fs实现多级联动

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAA0gAAAEdCAIAAAC5WdDhAAAgAElEQVR4nO3da3Mc153f8X4feq5lFR

  6. Android 文件读写

    一.分类 文件读写作为Android四大数据存储方式之一,又分为内部存储和外部存储两种: (1)内部存储(Internal storage): 总是可用. 文件默认情况存储在/data/data/包名 ...

  7. Neutron 如何支持多种 network provider - 每天5分钟玩转 OpenStack(70)

    Neutron 的架构是非常开放的,可以支持多种 network provider,只要遵循一定的设计原则和规范.本节我们将开始讨论这个主题. 先讨论一个简单的场景:在 Neutorn 中使用 lin ...

  8. EntityFramework之孩子删除(四)(你以为你真的懂了?)

    前言 从表面去看待事物视线总有点被层层薄雾笼罩的感觉,当你静下心来思考并让指尖飞梭于键盘之上,终将会拨开浓雾见青天.这是我切身体验. 在EF关系配置中,我暂且将主体对象称作为父亲,而依赖对象称作为孩子 ...

  9. Markdown编辑器入门

    欢迎使用博客园的Markdown编辑器 前言 今天早上起来在Ubuntu下操作,所以不能使用Windows Live Writer.所以就直接使用博客园的后台编辑器,开始以为博客园出错了,怎么编辑都没 ...

  10. Hawk: 20分钟无编程抓取大众点评17万数据

    1. 主角出场:Hawk介绍 Hawk是沙漠之鹰开发的一款数据抓取和清洗工具,目前已经在Github开源.详细介绍可参考:http://www.cnblogs.com/buptzym/p/545419 ...