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/7/21 15:52:49 阅读更多 →
终极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/7/21 15:52:49 阅读更多 →
网安面试真相:为什么你知识点全会,面试却总是挂科?

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

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

2026/7/21 15:51:49 阅读更多 →

最新新闻

C++ TCP同步文件下载器实现:从Socket API到粘包处理实战

C++ TCP同步文件下载器实现:从Socket API到粘包处理实战

1. 项目概述与核心价值 最近在整理一些老项目的代码,翻到了一个用纯C和Windows Socket API实现的TCP文件下载工具。这个项目虽然不大,但麻雀虽小五脏俱全,它完整地走了一遍TCP同步通信的流程,从建立连接到收发数据,再到…

2026/7/21 20:45:17 阅读更多 →
2026年Java面试高效复习策略:构建知识体系与场景化应用

2026年Java面试高效复习策略:构建知识体系与场景化应用

如果你正在准备2026年的Java面试,可能会陷入一个典型的困境: 面试范围越来越广,从Java基础、并发、JVM、MySQL到Spring全家桶,还要准备场景题、八股文,甚至现在连大模型相关的知识都可能被问到。 你感觉需要复习的知…

2026/7/21 20:45:17 阅读更多 →
C++重制《植物大战僵尸》:从游戏循环到对象池的完整实践指南

C++重制《植物大战僵尸》:从游戏循环到对象池的完整实践指南

1. 项目概述:为什么选择用C重制《植物大战僵尸》?如果你是一个对游戏开发感兴趣,尤其是对C这门“硬核”语言有学习热情的开发者,那么“从零构建一个《植物大战僵尸》重制版”这个项目,绝对是一个能让你从入门到进阶&am…

2026/7/21 20:45:17 阅读更多 →
Data as a Service(DaaS)核心原理与工程落地实践

Data as a Service(DaaS)核心原理与工程落地实践

我不能基于您提供的输入内容生成符合要求的博文。原因如下:输入内容实质为一篇已被发布在第三方媒体平台(Towards AI)的署名文章的元信息片段,包含明确的版权声明、作者署名、出版方标识(“Originally published on To…

2026/7/21 20:45:17 阅读更多 →
决策树分裂标准:信息熵与错分率的本质差异与实战选择

决策树分裂标准:信息熵与错分率的本质差异与实战选择

1. 项目概述:为什么一棵树的“切口”位置,比树长得高不高更重要?在机器学习实战中,我见过太多人把决策树当成黑箱——调个sklearn.tree.DecisionTreeClassifier,跑完fit()就急着看准确率,结果模型在训练集上…

2026/7/21 20:45:17 阅读更多 →
WebExtension Skip Redirect:高效解决浏览器重定向问题的完整技术方案

WebExtension Skip Redirect:高效解决浏览器重定向问题的完整技术方案

WebExtension Skip Redirect:高效解决浏览器重定向问题的完整技术方案 【免费下载链接】webextension-skip-redirect Some web pages use intermediary pages before redirecting to a final page. This add-on tries to extract the final url from the intermedia…

2026/7/21 20:44:17 阅读更多 →

日新闻

Octane Render与C4D汉化版安装与优化指南

Octane Render与C4D汉化版安装与优化指南

1. Octane Render与C4D的黄金组合:为什么选择这个方案?在三维创作领域,渲染器的选择往往决定了作品的最终呈现质量和工作效率。作为Cinema 4D(C4D)用户,Octane Render的GPU加速特性与实时预览功能&#xff…

2026/7/21 0:00:19 阅读更多 →
GPMC接口设计:异步/同步模式与多路复用配置实战

GPMC接口设计:异步/同步模式与多路复用配置实战

1. GPMC接口设计:从硬件连接到软件配置的全局视角在嵌入式系统开发中,尤其是基于TI Sitara系列如AM263x这类高性能微控制器的项目里,外部存储器的扩展几乎是绕不开的一环。无论是存放大量非易失性代码的NOR Flash,还是作为高速数据…

2026/7/21 0:00:19 阅读更多 →
UE5 GAS框架下RPG被动技能系统:从核心原理到实战实现

UE5 GAS框架下RPG被动技能系统:从核心原理到实战实现

1. 项目概述:UE5 GAS RPG被动技能的核心价值在UE5里用GAS(Gameplay Ability System)做RPG游戏,主动技能像是你手里的武器,按一下打一下,逻辑直接,反馈也快。但被动技能,它更像是你身…

2026/7/21 0:00:19 阅读更多 →

周新闻

Go语言静态资源打包方案对比与实践指南

Go语言静态资源打包方案对比与实践指南

1. 项目背景与核心需求在Go语言开发中,我们经常需要处理静态资源文件的打包问题。无论是Web应用的模板文件、前端资源,还是配置文件、证书等,都需要随程序一起分发。传统做法是将这些文件与编译后的二进制文件放在同一目录下,但这…

2026/7/21 8:48:31 阅读更多 →
Go语言实现高性能LDAP认证服务的架构与实践

Go语言实现高性能LDAP认证服务的架构与实践

1. 项目背景与核心价值LDAP(轻量级目录访问协议)作为企业级身份认证的黄金标准,已经服务了超过80%的财富500强公司。我在金融科技领域实施统一认证体系时,发现传统Java方案存在启动慢、内存占用高等痛点。而Go语言凭借其协程并发模…

2026/7/21 5:34:47 阅读更多 →
【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

【AI面试官实战指南】:用ChatGPT模拟10类高频技术岗面试,3天提升应答精准度92%

更多请点击: https://intelliparadigm.com 第一章:AI面试官实战指南的核心价值与适用场景 AI面试官并非替代人类HR的“黑箱工具”,而是以可解释、可审计、可迭代的方式,赋能招聘全链路的关键基础设施。其核心价值在于将主观经验沉…

2026/7/21 8:25:39 阅读更多 →

月新闻