Redis 缓存淘汰策略
Redis 缓存淘汰策略是当内存使用达到上限时Redis 自动清理部分数据以腾出空间的核心机制官方共定义了 ‌8 种主流策略‌分为两大类别一、8种淘汰策略分类针对所有键的策略‌noeviction默认‌内存满时拒绝写入新数据直接返回OOM错误读请求可正常执行。allkeys-lru‌从所有键中淘汰最近最少使用的数据是纯缓存场景的首选。allkeys-lfu‌从所有键中淘汰访问频次最低的数据能更精准保留热点数据。allkeys-random‌从所有键中随机淘汰部分键性能开销极低。仅针对设置了过期时间的键的策略‌volatile-lru‌仅从带过期时间的键中淘汰最近最少使用的数据保护永久数据。volatile-lfu‌仅从带过期时间的键中淘汰访问频次最低的数据。volatile-random‌仅从带过期时间的键中随机淘汰部分键。volatile-ttl‌优先淘汰剩余存活时间最短的键适配即将过期的数据清理场景。二、核心算法差异LRU‌基于访问时间维度优先淘汰长时间未被访问的数据适配冷热数据分界清晰的业务场景。LFU‌基于访问频次维度优先淘汰访问次数少的数据相比LRU能更稳定保留长期热点数据实现逻辑更复杂。三、配置与选型建议动态生效命令执行 config set maxmemory-policy allkeys-lru 即可实时切换策略。持久配置在Redis配置文件中修改 maxmemory-policy 参数重启后永久生效。选型参考纯缓存场景推荐allkeys-lru混合存储场景推荐volatile-lru避免误删未设置过期时间的核心业务数据。四LRU实现最简单方法实现 LRULeast Recently Used最近最少使用缓存最简单的方法取决于你的应用场景是‌工程落地‌还是‌面试/算法考察‌。工程落地最简单继承 LinkedHashMap (Java)在 Java 实际开发中无需手写链表直接利用 JDK 自带的 LinkedHashMap 即可快速实现一个线程非安全的 LRU 缓存。这是最简洁、最高效的工程实现方式。‌核心原理‌LinkedHashMap 内部维护了一个双向链表来记录插入顺序或访问顺序。通过构造函数开启“访问顺序模式”并重写 removeEldestEntry 方法即可自动淘汰最久未使用的数据。‌代码示例importjava.util.LinkedHashMap;importjava.util.Map;publicclassSimpleLRUCacheK,VextendsLinkedHashMapK,V{privatefinalintcapacity;publicSimpleLRUCache(intcapacity){// 第三个参数 true 表示按照访问顺序排序false 表示按照插入顺序排序super(capacity,0.75f,true);this.capacitycapacity;}OverrideprotectedbooleanremoveEldestEntry(Map.EntryK,Veldest){// 当地图大小超过指定容量时移除最老的条目returnsize()capacity;}}简单测试一下publicclassLRUTest{publicstaticvoidmain(String[]args){// 创建容量为 3 的 LRU 缓存LRUCacheInteger,StringcachenewLRUCache(3);// 1. 插入数据cache.put(1,A);cache.put(2,B);cache.put(3,C);System.out.println(初始状态: cache);// 输出: {1A, 2B, 3C}// 2. 访问 Key 1将其移至链表尾部变为最近使用cache.get(1);System.out.println(访问1后: cache);// 输出: {2B, 3C, 1A}// 3. 插入新数据 Key 4此时容量已满应淘汰最久未使用的 Key 2cache.put(4,D);System.out.println(插入4后: cache);// 输出: {3C, 1A, 4D}// 验证Key 2 已被淘汰返回 nullSystem.out.println(获取2: cache.get(2));// 输出: null}}关键细节说明‌accessOrder true‌这是灵魂参数。若设为 false默认链表仅按插入顺序排列无法体现“最近使用”也就无法实现 LRU。‌removeEldestEntry‌该方法在每次 put 操作后自动调用。返回 true 时LinkedHashMap 会自动移除双向链表头部的节点即 eldest。‌线程安全‌上述实现是非线程安全的。若需在多线程环境使用建议通过 Collections.synchronizedMap(new LRUCache(capacity)) 进行包装或在方法级别加锁。优点‌代码极少逻辑清晰JDK 原生支持性能可靠。‌缺点‌非线程安全多线程环境需加锁或使用 Collections.synchronizedMap且无法自定义更复杂的淘汰逻辑。2. 前端/脚本语言最简单使用 Map 手动维护顺序 (JavaScript/Python)在 JavaScript 或 Python 等动态语言中没有现成的“访问顺序 LinkedHashMap”最简单的实现是利用 Map 对象保证插入顺序配合删除和重新插入操作来模拟“最近使用移到头部”的逻辑。‌JavaScript 代码示例classLRUCache{constructor(capacity){this.capacitycapacity;this.cachenewMap();}get(key){if(!this.cache.has(key))return-1;// 关键步骤先删除再重新插入将其移到 Map 末尾代表最近使用constvaluethis.cache.get(key);this.cache.delete(key);this.cache.set(key,value);returnvalue;}put(key,value){if(this.cache.has(key)){this.cache.delete(key);// 如果存在先删除以更新位置}elseif(this.cache.sizethis.capacity){// 如果满了删除 Map 的第一个元素最久未使用constfirstKeythis.cache.keys().next().value;this.cache.delete(firstKey);}this.cache.set(key,value);// 插入到末尾}}优点‌逻辑直观利用了 Map 的有序特性无需实现复杂的链表节点结构。‌注意‌Map 的 keys().next().value 获取第一个键的时间复杂度在某些引擎中可能不是严格的 O(1)但在大多数现代 JS 引擎中性能足够好。3. 面试/算法考察标准解法HashMap 双向链表如果是在面试中被问到“如何实现 LRU”面试官通常希望看到你理解底层数据结构而不是调用库函数。此时“最简单”指的是‌逻辑最清晰的标准解法‌即组合使用 ‌HashMap‌ 和 ‌双向链表‌。‌核心思路‌‌HashMap‌提供 O(1) 的查找能力Key 映射到双向链表的节点。‌双向链表‌维护数据的访问顺序。‌头部‌最近使用的数据。‌尾部‌最久未使用的数据。‌操作逻辑‌‌Get‌从 HashMap 找到节点将该节点移动到链表头部。‌Put‌若 Key 存在更新值并移动到链表头部。若 Key 不存在创建新节点放入头部。若容量已满删除链表尾部节点并从 HashMap 中移除对应 Key。‌为什么不用单向链表或数组‌‌数组‌移动元素需要大量拷贝时间复杂度 O(N)。‌单向链表‌删除节点时需要知道前驱节点查找前驱需要 O(N)无法实现 O(1) 删除。‌双向链表‌可以在 O(1) 时间内完成节点的删除和移动。‌总结建议‌‌实际项目‌直接用 LinkedHashMap (Java) 或 Caffeine 库不要重复造轮子。‌前端开发‌用 Map 模拟简单有效。‌面试笔试‌必须手写 HashMap 双向链表并注意处理头尾指针的边界情况建议使用虚拟头尾节点简化代码。五LinkedHashMap 实现LRU原理LinkedHashMap 实现 LRULeast Recently Used最近最少使用缓存的核心原理在于其内部维护了一套‌双向链表‌来记录元素的访问或插入顺序并结合 HashMap 的哈希查找能力从而在保证 O(1) 查找效率的同时能够以 O(1) 的时间复杂度维护数据的“新鲜度”。以下是其实现 LRU 的具体机制拆解数据结构基础HashMap 双向链表LinkedHashMap 继承自 HashMap因此它保留了 HashMap数组 单向链表/红黑树 的结构用于快速定位数据。在此基础上它额外增加了一个‌双向链表‌结构‌节点改造‌HashMap中的 Entry 节点在 LinkedHashMap中被扩展为包含 before 和 after 指针的双向链表节点。‌头尾哨兵‌内部维护一个特殊的 header 节点或在 Java 8 中通过 head 和 tail 引用形成一个循环双向链表。header.after或 head指向链表中‌最久未使用‌的节点。header.before或 tail指向链表中‌最近使用‌的节点。2. 两种排序模式LinkedHashMap 构造函数中有一个关键参数 accessOrder‌false默认‌‌插入顺序‌。元素按照放入 Map 的顺序排列新元素加到链表尾部。这种模式不体现 LRU 特性。‌true‌‌访问顺序‌。这是实现 LRU 的关键。每当调用 get() 或 put()更新已存在的 key时被操作的节点会被移动到双向链表的‌尾部‌即最近使用端。3. LRU 核心逻辑实现步骤A. 访问时移动节点保持新鲜度当 accessOrder 为 true 时‌Get 操作‌通过 HashMap 快速找到节点后调用内部方法将该节点从当前位置移除并重新链接到双向链表的尾部。‌Put 操作‌如果 Key 已存在更新 Value 后同样将该节点移动到链表尾部。这一过程确保了‌链表头部始终是最久未被访问的数据链表尾部始终是最近被访问的数据。‌B. 自动淘汰机制移除最旧数据为了实现缓存容量限制LinkedHashMap 提供了一个受保护的方法 removeEldestEntry(Map.EntryK,V eldest)。‌默认行为‌该方法默认返回 false即不删除任何元素。‌LRU 实现技巧‌用户只需继承 LinkedHashMap 并重写该方法当 size() capacity 时返回 true。‌触发时机‌每次执行 put 操作添加新元素后LinkedHashMap 会自动调用 removeEldestEntry。如果返回 true它会自动移除双向链表‌头部‌header.after的节点因为那里存放的就是最久未使用的数据。4. 代码示例通过极简的代码即可实现一个标准的 LRU 缓存importjava.util.LinkedHashMap;importjava.util.Map;publicclassLRUCacheK,VextendsLinkedHashMapK,V{privatefinalintcapacity;publicLRUCache(intcapacity){// 初始容量, 负载因子0.75, accessOrdertrue开启访问顺序模式super(capacity,0.75f,true);this.capacitycapacity;}OverrideprotectedbooleanremoveEldestEntry(Map.EntryK,Veldest){// 当当前大小超过指定容量时移除最老的条目链表头部returnsize()capacity;}}总结LinkedHashMap 实现 LRU 的本质是利用 ‌HashMap‌ 保证 get/put 的查找效率为 O(1)。利用 ‌双向链表‌ 维护访问顺序通过 accessOrdertrue 确保每次访问都将节点移至尾部。利用 ‌removeEldestEntry‌ 回调机制在插入新数据时自动检查并移除链表头部的“最老”数据从而严格控制缓存容量。这种实现方式比手动维护 HashMap 双向链表 更加简洁、安全且由 JDK 底层优化是 Java 工程中实现 LRU 缓存的首选方案。

相关新闻

MinecraftForge模组开发终极指南:从入门到精通的高效开发实践

MinecraftForge模组开发终极指南:从入门到精通的高效开发实践

MinecraftForge模组开发终极指南:从入门到精通的高效开发实践 【免费下载链接】MinecraftForge Modifications to the Minecraft base files to assist in compatibility between mods. New Discord: https://discord.minecraftforge.net/ 项目地址: https://gitc…

2026/9/26 19:06:53 阅读更多 →
终极GIMP界面优化指南:5分钟让免费软件拥有Photoshop体验

终极GIMP界面优化指南:5分钟让免费软件拥有Photoshop体验

终极GIMP界面优化指南:5分钟让免费软件拥有Photoshop体验 【免费下载链接】PhotoGIMP A Patch for GIMP 3 for Photoshop Users 项目地址: https://gitcode.com/GitHub_Trending/ph/PhotoGIMP 还在为GIMP的复杂界面而烦恼吗?PhotoGIMP为您带来革命…

2026/10/14 6:39:47 阅读更多 →
网安面试真相:为什么你知识点全会,面试却总是挂科?

网安面试真相:为什么你知识点全会,面试却总是挂科?

📌 前言很多新人刷题无数、笔记满满、漏洞全会复现,但是一到面试就挂。面试官真正淘汰新人的原因,从来不是你不会漏洞,而是你没有工程思维、没有实战逻辑、只会背诵答案。本篇拆解网安面试“隐形扣分点”,帮你解决学得…

2026/10/10 21:23:07 阅读更多 →

最新新闻

C#调用WebService获取PDF转图片:选型与踩坑实战

C#调用WebService获取PDF转图片:选型与踩坑实战

做C#开发这几年,遇到“调用WebService获取PDF文件再转换为图片”这种需求不算少。可能是一个审批系统需要预览合同,也可能是一个报表平台需要把服务端生成的文件转成缩略图展示。总之核心工作就两件事:把远程文件拿下来,再在本地转…

2026/10/14 6:40:29 阅读更多 →
Unity Spark实战:在浏览器中用AI自然语言快速做游戏原型

Unity Spark实战:在浏览器中用AI自然语言快速做游戏原型

看到“Unity Spark 正式发布”这条消息的时候,我第一反应是:又来了。这年头但凡和 AI 沾边的工具都在喊“原生支持 AI”,口号早就被用烂了。但等我真正在浏览器里打开这个基于 AI 的游戏开发环境,亲手生成一个场景、跑通一次跳跃、…

2026/10/14 6:40:29 阅读更多 →
仓颉语言属性(prop)完全指南:getter/setter 定义、抽象属性与继承覆盖实战

仓颉语言属性(prop)完全指南:getter/setter 定义、抽象属性与继承覆盖实战

文档编程语言 【免费下载链接】cangjie_docs 仓颉编程语言开发者文档。 项目地址: https://gitcode.com/Cangjie/cangjie_docs 点击查看 免费下载 属性(Properties)是仓颉语言中用于间接获取和设置值的语言机制:它通过一个 gette…

2026/10/14 6:40:29 阅读更多 →
从Node到Bun:JavaScript运行时与工具链的工程效率革命

从Node到Bun:JavaScript运行时与工具链的工程效率革命

1. 为什么我把重心从 Node 切到了 Bun先说结论:Bun 不是又一个跑得更快的 Node,它是一整套重新设计过的 JavaScript 运行时和工具链。我最初对它的态度是观望,因为这类"下一代运行时"的宣发见过太多次了,但真正在几个中…

2026/10/14 6:40:29 阅读更多 →
C#对接WebService拉取PDF并转图片:从接口调到部署避坑

C#对接WebService拉取PDF并转图片:从接口调到部署避坑

前一阵接手一个对接任务,对方是个运行了十多年的老系统,只对外暴露SOAP风格的WebService接口。业务要求很直接:通过这个接口把PDF文件拉到我们这边,再转成图片,放到Web端做在线预览和打印存档。这类需求在C#开发里非常…

2026/10/14 6:40:29 阅读更多 →
纯Python实现猜数字游戏:从零到避坑的完整指南

纯Python实现猜数字游戏:从零到避坑的完整指南

猜数字游戏大概是很多人的第一个编程项目。它不像计算器那样枯燥,也不需要复杂的界面,但一套完整流程走下来,变量、输入输出、条件判断、循环、异常处理这些编程入门核心概念全部能练到。我最近又把这个小项目从头写了一遍,用最基…

2026/10/14 6:39:29 阅读更多 →

日新闻

AnyPS5通用适配层设计:兼容性与性能的工程取舍

AnyPS5通用适配层设计:兼容性与性能的工程取舍

1. 从"AnyPS5"这个名字说起:它到底想解决什么问题第一次看到"AnyPS5"这个标题,我脑子里冒出来的第一个念头是:这大概率是一个围绕"跨平台运行"或者"通用适配"做文章的项目。名字里的"Any"…

2026/10/14 0:00:41 阅读更多 →
Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

Flutter跨平台开发实战:二手交易应用与HarmonyOS适配

1. 项目概述:Flutter跨平台二手交易应用开发作为一名长期从事移动应用开发的工程师,我最近完成了一个基于Flutter框架的二手物品交易平台项目。这个项目最吸引我的地方在于它完美结合了Flutter的跨平台优势与HarmonyOS的生态特性,实现了"…

2026/10/14 0:00:41 阅读更多 →
DFS算法解决飞机降落调度问题实战

DFS算法解决飞机降落调度问题实战

1. 项目背景与核心思路飞机降落问题是一个经典的调度优化场景,也是算法竞赛和面试中的高频题目。这个题目要求我们合理安排多架飞机的降落顺序和时间,确保所有飞机都能安全着陆而不发生冲突。在实际航空管制中,这类问题直接关系到飞行安全和机…

2026/10/14 0:00:41 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/13 16:22:04 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 22:01:27 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/13 14:57:39 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 18:11:17 阅读更多 →