缓存淘汰算法LRU-K,2Q(Two queues)

2023-11-03 07:40

本文主要是介绍缓存淘汰算法LRU-K,2Q(Two queues),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.LRU-K

1.1 简介

LRU-K中的K代表最近使用的次数,LRU可以当作LRU-1。LRU-K主要目的是为了解决LRU算法的缓存污染问题。

什么是缓存污染?

当数据访问次数非常少,甚至只会被访问一次,数据服务完访问请求后还继续留在缓存中,白白占用缓存空间,这就是缓存污染。

1.2 原理

相比LRU,LRU-K除了缓存队列还要维护一个访问历史队列,这个队列不缓存数据,仅记录数据的历史访问次数。当数据访问次数达到k次时,数据才放入缓存队列。历史队列、缓存队列的维护与LRU中缓存队列的维护一样,遵循LRU原则。
在这里插入图片描述

1.3 过程

(1). 数据第一次被访问,加入到访问历史列表;

(2). 如果数据在访问历史列表里后没有达到K次访问,则按照一定规则(FIFO,LRU)淘汰;

(3). 当访问历史队列中的数据访问次数达到K次后,将数据索引从历史队列删除,将数据移到缓存队列中,并缓存此数据,缓存队列重新按照时间排序;

(4). 缓存数据队列中被再次访问后,重新排序;

(5). 需要淘汰数据时,淘汰缓存队列中排在末尾的数据,即:淘汰“倒数第K次访问离现在最久”的数据。

LRU-K具有LRU的优点,同时能够避免LRU的缺点,实际应用中LRU-2是综合各种因素后最优的选择,LRU-3或者更大的K值命中率会高,但适应性差,需要大量的数据访问才能将历史访问记录清除掉。

1.4 实现

// 直接继承我们前面写好的LRUCache
public class LRUKCache extends LRUCache {private int k; // 进入缓存队列的评判标准private LRUCache historyList; // 访问数据历史记录public LRUKCache(int cacheSize, int historyCapacity, int k) {super(cacheSize);this.k = k;this.historyList = new LRUCache(historyCapacity);}@Overridepublic Integer get(Integer key) {// 记录数据访问次数Integer historyCount = historyList.get(key);historyCount = historyCount == null ? 0 : historyCount;historyList.put(key, ++historyCount);return super.get(key);}@Overridepublic Integer put(Integer key, Integer value) {if (value == null) {return null;}// 如果已经在缓存里则直接返回缓存中的数据if (super.get(key) != null) {return super.put(key, value);;}// 如果数据历史访问次数达到上限,则加入缓存Integer historyCount = historyList.get(key);historyCount = historyCount == null ? 0 : historyCount;if (historyCount >= k) {// 移除历史访问记录historyList.remove(key);return super.put(key, value);}}
}
————————————————
版权声明:本文为CSDN博主「沙滩de流沙」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_41231928/article/details/120593579

2. 2Q (Tow Queues)

2.1 简介

2Q算法类似LRU-2,不同点在于2Q将LRU-2算法中的访问历史队列(仅作记录不缓存数据)改为FIFO缓存队列。即,2Q算法有两个缓存队列,一个FIFO队列,一个LRU队列。

2.2 原理

当数据第一次被访问时,2Q算法将数据缓存在FIFO队列中,数据被第二次访问时,从FIFO队列中移除并添加至LRU队列中,两个队列按照自己的方法淘汰数据。
在这里插入图片描述
(1). 新访问的数据插入到FIFO队列;

(2). 如果数据在FIFO队列中一直没有被再次访问,则最终按照FIFO规则淘汰;

(3). 如果数据在FIFO队列中被再次访问,则将数据移到LRU队列头部;

(4). 如果数据在LRU队列再次被访问,则将数据移到LRU队列头部;

(5). LRU队列淘汰末尾的数据。

参考:
LRU-K和2Q缓存算法介绍
面试官:你知道 LRU算法 —— 缓存淘汰算法吗?

这篇关于缓存淘汰算法LRU-K,2Q(Two queues)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/336639

相关文章

Redis缓存问题与缓存更新机制详解

《Redis缓存问题与缓存更新机制详解》本文主要介绍了缓存问题及其解决方案,包括缓存穿透、缓存击穿、缓存雪崩等问题的成因以及相应的预防和解决方法,同时,还详细探讨了缓存更新机制,包括不同情况下的缓存更... 目录一、缓存问题1.1 缓存穿透1.1.1 问题来源1.1.2 解决方案1.2 缓存击穿1.2.1

Python中的随机森林算法与实战

《Python中的随机森林算法与实战》本文详细介绍了随机森林算法,包括其原理、实现步骤、分类和回归案例,并讨论了其优点和缺点,通过面向对象编程实现了一个简单的随机森林模型,并应用于鸢尾花分类和波士顿房... 目录1、随机森林算法概述2、随机森林的原理3、实现步骤4、分类案例:使用随机森林预测鸢尾花品种4.1

Redis与缓存解读

《Redis与缓存解读》文章介绍了Redis作为缓存层的优势和缺点,并分析了六种缓存更新策略,包括超时剔除、先删缓存再更新数据库、旁路缓存、先更新数据库再删缓存、先更新数据库再更新缓存、读写穿透和异步... 目录缓存缓存优缺点缓存更新策略超时剔除先删缓存再更新数据库旁路缓存(先更新数据库,再删缓存)先更新数

el-select下拉选择缓存的实现

《el-select下拉选择缓存的实现》本文主要介绍了在使用el-select实现下拉选择缓存时遇到的问题及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的... 目录项目场景:问题描述解决方案:项目场景:从左侧列表中选取字段填入右侧下拉多选框,用户可以对右侧

SpringBoot使用注解集成Redis缓存的示例代码

《SpringBoot使用注解集成Redis缓存的示例代码》:本文主要介绍在SpringBoot中使用注解集成Redis缓存的步骤,包括添加依赖、创建相关配置类、需要缓存数据的类(Tes... 目录一、创建 Caching 配置类二、创建需要缓存数据的类三、测试方法Spring Boot 熟悉后,集成一个外

使用Spring Cache时设置缓存键的注意事项详解

《使用SpringCache时设置缓存键的注意事项详解》在现代的Web应用中,缓存是提高系统性能和响应速度的重要手段之一,Spring框架提供了强大的缓存支持,通过​​@Cacheable​​、​​... 目录引言1. 缓存键的基本概念2. 默认缓存键生成器3. 自定义缓存键3.1 使用​​@Cacheab

Nacos客户端本地缓存和故障转移方式

《Nacos客户端本地缓存和故障转移方式》Nacos客户端在从Server获得服务时,若出现故障,会通过ServiceInfoHolder和FailoverReactor进行故障转移,ServiceI... 目录1. ServiceInfoHolder本地缓存目录2. FailoverReactorinit

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个