Redis-缓存过期淘汰策略

news2024/11/27 20:32:47

缓存淘汰策略

生产上redis内存设置为多少

设置为最大内存的 3/4

redis 会占用物理机多少内存

默认大小是 0,64 位系统下表示不限制内存大小,32位系统表示 3G

如何设置修改redis内存大小

  1. config get maxmemory 查看
  2. 修改方式
    1. 配置文件 单位是字节

2. <font style="color:#000000;">临时修改,重启后失效 config set maxmemory 104857600</font>

如果redis内存满了会怎么样

redis 将会报错:(error) OOM command not allowed when used memory > ‘maxmemory’

通过命令查看 redis 内存使用情况?

info memory

redis 对于过期 key 的三种不同删除策略

定时删除:创建kv的同时cpu会创建定时器,内存友好,cpu占用高

惰性删除:再次访问这个 key 的时候才会去检查过期时间,内存不友好

定时删除:每隔一段时间去抽样扫描一定(注意不是所有)数量的key是否过期,并可通过限制执行的频率和时长来控制对 cpu 的影响,折中,但可能存留较多过期key,并且需要根据具体情况合适的设置频率和时长

如果执行时间太长,退化成定时。太短则又会出现过期key太多

引出兜底方案,缓存淘汰策略

redis 缓存淘汰策略

8种内存淘汰策略

  • noevition: 不操作 默认,看上面oom案例
  • allkeys-lru: 对所有 key 使用 lru
  • volatile-lru: 对所有设置了过期时间的key lru
  • allkeys-random
  • volatile-random
  • volatile-ttl: 删除快要过期
  • allkeys-lfu lfu
  • volatile-lfu

修改 -> maxmemory-policy

总结记忆

  1. 2个维度
    1. 过期键中筛选 allkeys
    2. 所有键中筛选 volatile
  2. 4个方面
    1. lru 最少使用,最长时间未被使用
    2. lfu 最不常用,一段时间内使用次数最少
    3. random 随机
    4. ttl

用哪种

后两种都对业务有精确的要求,推荐 allkeys-lru

lru算法手写,最近最少使用算法

leetcode 146

哈希链表

基于 LinkedHashMap 的写法

public class LruCacheDemo<K,V> extends LinkedHashMap<K,V> {
    private int capacity;

    public LruCacheDemo(int capacity) {
        super(capacity, 0.75f, false); // true = accessOrder false insertionOrder
        this.capacity = capacity;
    }

    @Override
    protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
        return super.size() > capacity;
    }

    public static void main(String[] args) {
        LruCacheDemo lruCacheDemo = new LruCacheDemo(3);
        lruCacheDemo.put(1, 1);
        lruCacheDemo.put(2, 2);
        lruCacheDemo.put(3, 3);
        System.out.println(lruCacheDemo.keySet());

        lruCacheDemo.put(4, 4);
        System.out.println(lruCacheDemo.keySet());

        lruCacheDemo.put(3, 3);
        System.out.println(lruCacheDemo.keySet());
        lruCacheDemo.put(3, 3);
        System.out.println(lruCacheDemo.keySet());
        lruCacheDemo.put(3, 3);
        System.out.println(lruCacheDemo.keySet());

        lruCacheDemo.put(5, 5);
        System.out.println(lruCacheDemo.keySet());
    }
}
/**
 * true
 * [1, 2, 3]
 * [2, 3, 4]
 * [2, 4, 3]
 * [2, 4, 3]
 * [2, 4, 3]
 * [4, 3, 5]
 */
// false,只看插入顺序,不看访问顺序,多次插入3,3的位置不变
/**
 * false
 *[1, 2, 3]
 * [2, 3, 4]
 * [2, 3, 4]
 * [2, 3, 4]
 * [2, 3, 4]
 * [3, 4, 5]
 */

手写的案例

// 手写 LruCache
public class MyLruCacheDemo {

    // map 负责查找,构建一个虚拟的双向链表,它里面安装的就是一个个Node节点,作为数据载体

    // 1 构造一个 Node 作为数据载体
    class Node<K, V> {
        K key;
        V value;
        Node<K, V> prev;
        Node<K, V> next;

        public Node() {
            this.prev = this.next = null;
        }
    }

    //2 构建一个虚拟的双向链表,里面安放的就是我们的Node
    class DoubleLinkedList<K, V> {
        Node<K, V> head;
        Node<K, V> tail;

        // 2.1 构造方法
        public DoubleLinkedList() {
            head = new Node<K, V>();
            tail = new Node<K, V>();
            head.next = tail;
            tail.prev = head;
        }

        //2.2 添加到头
        public void addFirst(Node<K, V> node) {
            node.next = head.next;
            node.prev = head;
            head.next.prev = node;
            head.next = node;
        }

        //2.3 删除节点
        public void remove(Node<K, V> node) {
            node.prev.next = node.next;
            node.next.prev = node.prev;
            node.prev = null;
            node.next = null;
        }

        //2.4 获得最后一个节点
        public Node<K, V> getLast() {
            return tail.prev;
        }
    }

    private int cacheSize;
    Map<Integer, Node<Integer, Integer>> map;
    DoubleLinkedList<Integer, Integer> doubleLinkedList;

    public MyLruCacheDemo(int cacheSize) {
        this.cacheSize = cacheSize; // 坑位
        map = new HashMap<>(); // 查找
        doubleLinkedList = new DoubleLinkedList<>();
    }

    public int get(int key) {
        if (!map.containsKey(key)) {
            return -1;
        }
        Node<Integer, Integer> node = map.get(key);
        doubleLinkedList.remove(node);
        doubleLinkedList.addFirst(node);
        return node.value;
    }

    // saveOrUpdate
    public void put(int key, int value) {
        if (map.containsKey(key)) { // update
            Node<Integer, Integer> node = map.get(key);
            node.value = value;
            doubleLinkedList.remove(node);
            doubleLinkedList.addFirst(node);
        } else {
            if (map.size() == cacheSize) { // 坑位满了
                Node<Integer, Integer> last = doubleLinkedList.getLast();
                map.remove(last.key);
                doubleLinkedList.remove(last);
            }
            // 才是新增
            Node<Integer, Integer> node = new Node<>();
            node.key = key;
            node.value = value;
            map.put(key, node);
            doubleLinkedList.addFirst(node);
        }
    }

    public static void main(String[] args) {
        MyLruCacheDemo lruCacheDemo = new MyLruCacheDemo(3);
        lruCacheDemo.put(1, 1);
        lruCacheDemo.put(2, 2);
        lruCacheDemo.put(3, 3);
        System.out.println(lruCacheDemo.map.keySet());
        lruCacheDemo.put(4, 4);
        System.out.println(lruCacheDemo.map.keySet());

        lruCacheDemo.put(3, 3);
        System.out.println(lruCacheDemo.map.keySet());

        lruCacheDemo.put(3, 3);
        System.out.println(lruCacheDemo.map.keySet());

        lruCacheDemo.put(5, 5);
        System.out.println(lruCacheDemo.map.keySet());

    }
}

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

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

相关文章

读数据工程之道:设计和构建健壮的数据系统04数据工程生命周期(下)

1. 获取 1.1. 在了解数据源、所用源系统的特征以及数据的存储方式之后&#xff0c;你需要收集数据 1.2. 数据工程生命周期的下一阶段是从源系统中获取数据 1.2.1. 源系统和获取代表了数据工程生命周期中最重要的瓶颈 1.2.2. 源系统通常不在你的直接控制范围内&#xff0c;可…

性能测试工具locust —— Python脚本参数化!

1.1.登录用户参数化 在测试过程中&#xff0c;经常会涉及到需要用不同的用户登录操作&#xff0c;可以采用队列的方式&#xff0c;对登录的用户进行参数化。如果数据要保证不重复&#xff0c;则取完不再放回&#xff1b;如可以重复&#xff0c;则取出后再返回队列。 def lo…

算法修炼之路之位运算

目录 一:位运算符及一些常用结论总结 1.给一个数n&#xff0c;确定它的二进制表示中的第x位是0还是1(位数从右向左0开始增加) 2.将一个数n的二进制表示形式的第x位修改成1 3.将一个数n的二进制表示的第x位修改为0 4.提取一个数n的二进制表示中最右侧的1 5.干掉一个数n的…

使用Android studio进行Unit Test中遇到的问题记录

1、模块本身代码运行不起来 提示&#xff1a; Cannot resolve method ‘getVolumes’ in ‘StorageManager’ Cannot resolve method ‘registerListener’ in ‘StorageManager’ Cannot resolve method ‘unregisterListener’ in ‘StorageManager’ 查看Android 源码&…

p20 docker自己commit一个镜像 p21 容器数据卷 p22mysql同步数据(国内镜像被封锁暂时往后放)p23具名挂载和匿名挂载

如何自己commit一个镜像 这里还是先引用一下老师的笔记 关于如何自己commit一个镜像这个问题目前因为从仓库中拉下来的Tomcat里面是没有项目的&#xff0c;所以把webapps.dist里面的拷贝到webapps里面去作为自己的镜像在commit一下 这里用Tomcat举例子首先把镜像拉取下来执…

C语言 | Leetcode C语言题解之第468题验证IP地址

题目&#xff1a; 题解&#xff1a; char * validIPAddress(char * queryIP) {int len strlen(queryIP);if (strchr(queryIP, .)) {// IPv4int last -1;for (int i 0; i < 4; i) {int cur -1;if (i 3) {cur len;} else {char * p strchr(queryIP last 1, .);if (p…

读懂RAG理论到实践

目录 LLM面临的问题RAG数据准备阶段检索生成阶段 RAG实战数据准备阶段数据提取数据清洗补充&#xff1a;去除停用词 分块&#xff08;Chunking&#xff09;分块的方法固定大小分块Sentence splitting&#xff08;句分割&#xff09;递归分割 补充&#xff1a;特殊分块 向量化&a…

Java项目实战II基于Java+Spring Boot+MySQL的作业管理系统设计与实现(源码+数据库+文档)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 在教育信息…

Spring Boot学习资源库:微服务架构的加速器

3 系统分析 3.1可行性分析 在进行可行性分析时&#xff0c;我们通常根据软件工程里方法&#xff0c;通过四个方面来进行分析&#xff0c;分别是技术、经济、操作和法律可行性。因此&#xff0c;在基于对目标系统的基本调查和研究后&#xff0c;对提出的基本方案进行可行性分析。…

网站集群批量管理-Ansible(playbook)

1.剧本概述 1. playbook 文件,用于长久保存并且实现批量管理,维护,部署的文件. 类似于脚本存放命令和变量 2. 剧本yaml格式,yaml格式的文件:空格,冒号 2. 区别 ans-playbookans ad-hoc共同点批量管理,使用模块批量管理,使用模块区别重复调用不是很方便,不容易重复场景部署服务…

视频流媒体解决方案,Liveweb国标GB28181视频监控汇聚平台

Liveweb视频监控国标平台指的是基于GB/T 28181协议的视频联网平台&#xff0c;可以对接各种符合国标GB/T 28181协议的视频平台、NVR录像机、网络监控摄像头、执法记录仪、应急布控球、移动单兵、无人机等设备。通过国标平台的联网&#xff0c;方便管理分布在不同地点的视频监控…

股指期货和股指期权有什么区别?

在金融衍生品的世界里&#xff0c;股权类衍生品无疑是其中的佼佼者&#xff0c;而股指期货和股指期权更是其中的佼佼者。尽管它们之间有着千丝万缕的联系&#xff0c;但它们之间的区别同样不容忽视。本文衍生股指君将详细解析股指期货和股指期权的核心区别。 一、交易的东西不…

【安装JDK和Android SDK】

安装JDK和Android SDK 1 前言2 下载2.1 下载途径2.2 JDK下载和安装2.2.1 下载2.2.2 安装并配置环境变量2.2.3 验证 2.3 SDK下载和安装2.3.1 下载2.3.2 安装2.3.3 环境变量配置2.3.4 验证 1 前言 在软件开发中&#xff0c;Android应用开发通常使用Android Studio&#xff0c;但…

进程守护化

文章目录 概念引入ps细节展示什么是进程组什么是会话细节演示有关指令的处理 用户级任务和进程组的关系关系不同 什么是守护进程如何创建守护进程 代码说明如何关闭守护进程 问题 概念引入 我们在之前的章节中已将看过进程相关的概念, 本篇介绍守护进程 进程还有进程组, 作业,…

Vue脚手架项目创建 --保姆级教程

Vue-项目创建 这里我默认已经安装好了脚手架&#xff0c;没装得可以看我上篇博客的安装教程。脚手架安装教程 脚手架提供了两种创建方式&#xff0c;我们以 vue ui 作为示例…… 1.输入 vue ui 进入图形界面进行项目配置 选择 一个你 的项目的存放路径&#xff0c;各自都不相…

[算法] 数组

1 二分查找 . - 力扣&#xff08;LeetCode&#xff09;. - 备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/binary-search/submissions/570732311/ 前闭后闭 class …

Word 中脚注和尾注的区别有哪些?如何正确使用它们?

在撰写学术论文、报告或其他需要引用资料的文章时&#xff0c;脚注和尾注是两种常用的标注方法。它们不仅可以为读者提供额外的背景信息&#xff0c;还能帮助整理文章中的引用来源。下面我们就来详细的了解一下什么是脚注和尾注。 脚注 脚注&#xff08;Footnote&#xff09;…

大学离散数学:开启逻辑与思维的奇妙之旅

在大学的知识殿堂中&#xff0c;离散数学犹如一颗璀璨的明珠&#xff0c;散发着独特的魅力。 离散数学是现代数学的一个重要分支&#xff0c;它主要研究离散对象的结构及其相互关系。与连续数学不同&#xff0c;离散数学处理的是离散的、可数的对象&#xff0c;如整数、图、集…

Kubernetes简介与部署+Pod管理与优化

一、简介 1.基础信息 在Docker 作为高级容器引擎快速发展的同时&#xff0c;在Google内部&#xff0c;容器技术已经应用了很多年Borg系统运行管理着成干上万的容器应用。Kubernetes项目来源于Borg&#xff0c;可以说是集结了Borg设计思想的精华&#xff0c;并且吸收了Borg系统…

动态线程池设计与实现

为什么要有动态线程池 ThreadPoolExecutor 核心线程参数对某些业务不知到设置多少合适调整参数需要重新启动服务没有告警功能 设计思路 流程设计 库表抽象 更新操作流程图 代码实现 GitCode - 全球开发者的开源社区,开源代码托管平台