【Redis】数据的淘汰策略

    

目录

淘汰策略方案(8种)

LRU和LFU策略的区别

使用建议

手搓LRU算法

方式一

方式二


        大家好,我是jstart千语。今天和大家回来聊一下redis,这次要讲的是它的淘汰策略。为什么需要淘汰策略呢,就是当redis里面的内存占满后,存不下数据了,那么新加入的数据该如何处理呢?这种处理的方式不同,就称为不同的数据淘汰策略。redis支持8种不同的淘汰策略。

淘汰策略方案(8种)

noeviction默认策略,不淘汰,当内存满时写入会报错(OOM)。适合读多写少的缓存场景
volatile-ttl从设置了过期时间的 key 中,优先淘汰即将过期的。
allkey-random随机淘汰一个 key。适用于不关心数据使用频率的场景。
volatile-random从设置了过期时间的 key 中随机淘汰一个。
allkeys-lru(最近最少使用)从所有 key 中淘汰最少使用的(LRU:Least Recently Used)。
volatile-lru(最近最少使用)从设置了过期时间的 key 中,淘汰最少使用的。
allkeys-lfu(频率)从所有 key 中淘汰最不常用的(LFU:Least Frequently Used)。
volatile-lfu(频率)从设置了过期时间的 key 中,淘汰最不常用的。


LRU和LFU策略的区别

LRU:最近最少使用,用当前时间减去最后一次访问的时间,这个值越大越先被淘汰。

例如:key1是5秒前被访问,key2是10秒前被访问,那么就是key2优先被淘汰。


LFU:最少频率使用,统计每个key的访问频率,值越小越先被淘汰。

例如:key1在5秒内被访问了3次,key2在10秒内被访问了5次。那么key2优先被淘汰。



使用建议

        1、优先使用allkeys-lru策略。充分利用LRU算法的优势,把最近最常访问的数据留在缓存中。如果业务中有明显的冷热数据区分,建议使用该策略。


为什么这里不使用LFU呢?:

因为数据使用频率可能是不固定的,在某一段时间内访问频率高,另外一段时间访问频率低,可能导致误删。具体还要看业务需求
 

        2、如果业务中数据访问频率区别不大,没有明显的冷热数据区分,建议使用allkeys-random,随机选择淘汰。

        3、如果业务中有置顶需求,可以使用volatile-lru策略,同时置顶数据不设置过期时间,这些置顶的数据就一直不被删除,会淘汰其他设置过期时间的数据。

        4、如果业务中有短时高频访问的数据,可以使用allkeys-lfu或者volatile-lfu策略。



手搓LRU算法

方式一

利用Java的LinkedHashMap天然支持按访问顺序排序,通过重写removeEldestEntry方法可实现LRU逻辑。

public class LRUCache<K, V> extends LinkedHashMap<K, V> {private final int capacity;public LRUCache(int capacity) {// 初始容量,负载因子,accessOrder=true表示按访问顺序排序super(capacity, 0.75f, true);this.capacity = capacity;}@Overrideprotected boolean removeEldestEntry(Map.Entry<K, V> eldest) {// 当大小超过容量时移除最旧元素return size() > capacity;}
}

使用示例:

LRUCache<String, String> cache = new LRUCache<>(3);
cache.put("a", "1");
cache.put("b", "2");
cache.get("a"); // 访问"a"使其变为最近使用
cache.put("c", "3");
cache.put("d", "4"); // 插入"d"时,容量超限,淘汰最久未使用的"b"

 注意:非线程安全,需在单线程环境使用或通过Collections.synchronizedMap包装。


方式二

手动实现(哈希表 + 双向链表)。实现O(1)时间复杂度的get和put操作,需结合哈希表与双向链表。

步骤:

  1. 定义节点结构:包含前后指针及键值。
  2. 维护双向链表:头部放最新访问节点,尾部为待淘汰节点。
  3. 哈希表映射:快速定位节点位置。
import java.util.HashMap;
import java.util.Map;public class ManualLRUCache<K, V> {static class Node<K, V> {K key;V value;Node<K, V> prev;Node<K, V> next;Node(K key, V value) {this.key = key;this.value = value;}}private final int capacity;private final Map<K, Node<K, V>> cache = new HashMap<>();private Node<K, V> head; // 虚拟头节点private Node<K, V> tail; // 虚拟尾节点public ManualLRUCache(int capacity) {this.capacity = capacity;head = new Node<>(null, null);tail = new Node<>(null, null);head.next = tail;tail.prev = head;}public V get(K key) {Node<K, V> node = cache.get(key);if (node == null) return null;moveToHead(node); // 访问后移至头部return node.value;}public void put(K key, V value) {Node<K, V> node = cache.get(key);if (node != null) {node.value = value;moveToHead(node);} else {node = new Node<>(key, value);cache.put(key, node);addToHead(node);if (cache.size() > capacity) {Node<K, V> removed = removeTail();cache.remove(removed.key);}}}private void moveToHead(Node<K, V> node) {removeNode(node);addToHead(node);}private void addToHead(Node<K, V> node) {node.prev = head;node.next = head.next;head.next.prev = node;head.next = node;}private void removeNode(Node<K, V> node) {node.prev.next = node.next;node.next.prev = node.prev;}private Node<K, V> removeTail() {Node<K, V> res = tail.prev;removeNode(res);return res;}
}

线程安全优化:

  • 使用ConcurrentHashMap替代HashMap。
  • 对链表操作加锁(如ReentrantLock或synchronized),但可能影响性能。
  • 考虑读写锁(ReadWriteLock),允许并发读,写时独占。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/75850.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【前端】Node.js一本通

近两天更新完毕&#xff0c;建议关注收藏点赞。 目录 复习Node.js概述使用fs文件系统模块path路径模块 http模块 复习 为什么JS可以在浏览器中执行 原理&#xff1a;待执行的JS代码->JS解析引擎 不同的浏览器使用不同的 JavaScript 解析引擎&#xff1a;其中&#xff0c;C…

【AI论文】JavisDiT: 具备层次化时空先验同步机制的联合音视频扩散Transformer

摘要&#xff1a;本文介绍了一种新型的联合音频-视频扩散变换器JavisDiT&#xff0c;该变换器专为同步音频-视频生成&#xff08;JAVG&#xff09;而设计。 基于强大的扩散变换器&#xff08;DiT&#xff09;架构&#xff0c;JavisDiT能够根据开放式用户提示同时生成高质量的音…

Java-实现公有字段自动注入(创建人、创建时间、修改人、修改时间)

文章目录 Mybatis-plus实现自动注入定义 MetaObjectHandler配置 MyBatis-Plus 使用 MetaObjectHandler实体类字段注解使用服务类进行操作测试 Jpa启用审计功能实现自动注入添加依赖启动类启用审计功能实现AuditorAware接口实体类中使用审计注解 总结 自动注入创建人、创建时间、…

金融机构开源软件风险管理体系建设

开源软件为金融行业带来了创新活力的同时&#xff0c;也引入了一系列独特的风险。金融机构需要构建系统化的风险管理体系&#xff0c;以识别和应对开源软件在全生命周期中的各种风险点。下面我们将解析开源软件在金融场景下的主要风险类别&#xff0c;并探讨如何建立健全的风险…

图形渲染中的定点数和浮点数

三种API的NDC区别 NDC全称&#xff0c;Normalized Device Coordinates Metal、Vulkan、OpenGL的区别如下&#xff1a; featureOpenGL NDCMetal NDCVulkan NDC坐标系右手左手右手z值范围[-1,1][0,1][0,1]xy视口范围[-1,1][-1,1][-1,1] GPU渲染的定点数和浮点数 定点数类型&a…

同花顺客户端公司财报抓取分析

目标客户端下载地址:https://ft.51ifind.com/index.php?c=index&a=download PC版本 主要难点在登陆,获取token中的 jgbsessid (每次重新登录这个字段都会立即失效,且有效期应该是15天的) 抓取jgbsessid 主要通过安装mitmproxy 使用 mitmdump + 下边的脚本实现监听接口…

QT工程建立

打开软件新建一个工程 选择chose 工程命名&#xff0c;选择保存路径&#xff0c;可以自己选择&#xff0c;但是不要有中文路径 默认的直接下一步 任意选一个下一步 点击完成 之后是这个界面&#xff0c;点击右下角的绿色三角形编译一下 实验内容 添加类 第一个是建立cpp和.h文件…

【NLP 53、投机采样加速推理】

目录 一、投机采样 二、投机采样改进&#xff1a;美杜莎模型 流程 改进 三、Deepseek的投机采样 流程 Ⅰ、输入文本预处理 Ⅱ、引导模型预测 Ⅲ、候选集筛选&#xff08;可选&#xff09; Ⅳ、主模型验证 Ⅴ、生成输出与循环 骗你的&#xff0c;其实我在意透了 —— 25.4.4 一、…

ffmpeg时间基与时间戳

时间基、时间戳 时间基&#xff1a;表示时间单位的分数&#xff0c;用来定义视频或音频流中时间的精度。其形式是一个分数&#xff0c;分子通常为 1&#xff0c;而分母则表示每秒的单位数。 时间戳&#xff1a;代表在时间轴里占了多少个格子&#xff0c;是特定的时间点。 时间…

激光加工中平面倾斜度的矫正

在激光加工中&#xff0c;加工平面的倾斜度矫正至关重要&#xff0c;直接影响加工精度和材料处理效果。以下是系统的矫正方法和步骤&#xff1a; 5. 验证与迭代 二次测量&#xff1a;加工后重新检测平面度&#xff0c;确认残余误差。 反馈优化&#xff1a;根据误差分布修正补偿…

算法刷题记录——LeetCode篇(2.2) [第111~120题](持续更新)

更新时间&#xff1a;2025-04-04 算法题解目录汇总&#xff1a;算法刷题记录——题解目录汇总技术博客总目录&#xff1a;计算机技术系列博客——目录页 优先整理热门100及面试150&#xff0c;不定期持续更新&#xff0c;欢迎关注&#xff01; 114. 二叉树展开为链表 给你二…

C语言学习笔记-9

九、结构体 构造类型&#xff1a; 不是基本类型的数据结构也不是指针类型&#xff0c; 它是若干个相同或不同类型的数据构成的集合 结构体类型&#xff1a; 结构体是一种构造类型的数据结构&#xff0c;是一种或多种基本类型或构造类型的数据的集合。 1.结构体类型定义 定…

Test——BUG篇

目录 一软件测试的生命周期 二BUG 1概念 2描述Bug 3Bug级别 4Bug的生命周期 三与开发人员发生争执怎么办 ​编辑1先自省&#xff1a;是否Bug描述不清晰 2站在用户角度考虑并抛出问题 3Bug定级有理有据 4不仅要提出问题&#xff0c;还要给出解决方案 5Bug评审 5.1…

【Block总结】HWAB,半小波注意力块|即插即用

论文信息 标题: HALF WAVELET ATTENTION ON M-NET+ FOR LOW-LIGHT IMAGE ENHANCEMENT 地址: arXiv:2203.01296 日期: 2022年3月 创新点 改进的分层架构 M-Net+: 提出了一个专为低光图像增强设计的改良分层模型 M-Net+。该架构旨在缓解采样过程中的空间信息损失问题。通过采用…

Spring 中的事务

&#x1f9fe; 一、什么是事务&#xff1f; &#x1f9e0; 通俗理解&#xff1a; 事务 一组操作&#xff0c;要么全部成功&#xff0c;要么全部失败&#xff0c;不能只做一半。 比如你转账&#xff1a; A 账户扣钱B 账户加钱 如果 A 扣了钱但 B 没收到&#xff0c;那就出问…

Flutter极速接入IM聊天功能并支持鸿蒙

Flutter极速接入IM聊天功能并支持鸿蒙 如果你们也是Flutter项目&#xff0c;想快速接入聊天&#xff0c;包括聊天的UI界面&#xff0c;强烈推荐这一家。因为我们已经完成了集成&#xff0c;使用非常稳定&#xff0c;集成也非常快捷方便。 而且&#xff0c;就在今天&#xff0c…

C# 类库生成后自动复制到指定目录

C# 类库生成后自动复制到指定目录 在C#中,当你开发了一个类库项目(通常是.NET Core或.NET Framework项目),你可能会希望在构建(Build)完成后自动将生成的DLL文件复制到指定的目录。有几种方法可以实现这个需求,下面是一些常用的方法: 方法1:使用MSBuild的AfterBuild…

13-产品经理-产品多分支平台管理

禅道16.0版本开始&#xff0c;优化和增强了产品的分支/平台功能&#xff0c;主要特点如下&#xff1a; 多分支/平台功能兼容各种大小型项目&#xff0c;项目/迭代可以关联对应产品的某个分支/平台。分支/平台支持灵活管理&#xff0c;可以把分支/平台理解为时间层面的概念&…

手搓多模态-04 归一化介绍

在机器学习中&#xff0c;归一化是一个非常重要的工具&#xff0c;它能帮助我们加速训练的速度。在我们前面的SiglipVisionTransformer 中&#xff0c;也有用到归一化层&#xff0c;如下代码所示&#xff1a; class SiglipVisionTransformer(nn.Module): ##视觉模型的第二层&am…

Qt 入门 1 之第一个程序 Hello World

Qt 入门1之第一个程序 Hello World 直接上操作步骤从头开始认识&#xff0c;打开Qt Creator&#xff0c;创建一个新项目&#xff0c;并依次执行以下操作 在Qt Creator中&#xff0c;一个Kits 表示一个完整的构建环境&#xff0c;包括编译器、Qt版本、调试器等。在上图中可以直…