redis缓存满了的话会发生什么?

线上问题

未及时加监控,导致线上redis被逐出,业务有损

示例:
一个key临时存储在redis等缓存中,如果该key在一段时间内有很大作用
比如一次业务请求,上游服务写入一个value,时长1小时,下游服务需要在1小时内读取它,并完成核心逻辑
如果被逐出后,导致下游拿不到数据,使得此次请求带来也业务问题

解决方法

redis 80%容量时添加监控,及时告警,及时进行业务处理。

学习文档

https://juejin.cn/post/6921884079830859789
在这里插入图片描述

影响

内存数据库,当其使用的内存超过物理内存限制后,内存和磁盘产生频繁的数据交换
导致Redis性能急剧下降

策略

通过配置参数maxmemoey来限制使用的内存大小。
当实际使用内存超过maxmemoey后,Redis提供了如下几种可选策略。

noeviction:(不驱逐,eviction表示驱逐)写请求返回错误
volatile-lru:使用lru算法删除设置了过期时间的键值对
volatile-lfu:使用lfu算法删除设置了过期时间的键值对
volatile-random:在设置了过期时间的键值对中随机进行删除
volatile-ttl:根据过期时间的先后进行删除,越早过期的越先被删除

allkeys-lru:在所有键值对中,使用lru算法进行删除
allkeys-lfu:在所有键值对中,使用lfu算法进行删除
allkeys-random:所有键值对中随机删除

附录

LRU - Least Recently Used

最近最少使用
最近访问的数据,后续很大概率还会被访问到
长时间未被访问的数据,应该被淘汰

LRU算法中数据会被放到一个链表中
链表的头节点为最近被访问的数据
链表的尾节点为长时间没有被访问的数据

LRU算法的核心实现是哈希表+双向链表
链表用来维护访问元素的顺序,哈希表可以在O(1)时间复杂度下进行元素访问

为什么是双向链表呢?
删除元素的话,需要获取前继节点

LFU - Least Frequently Used

LRU算法有一个问题,当一个长时间不被访问的key,偶尔被访问一下后,可能会造成一个比该key访问更频繁的key被淘汰。
LRU算法对key的冷热程度判断不准确。

最不经常使用
按照访问频率来判断key的冷热程度,每次删除的是一段时间内访问频率较低的数据,比LRU算法更准确

如何设计?

  1. 需要存储k-v的map:keyToVal

  2. 需要存储某个k的访问频次的map:keyToFreq

  3. 需要存储当前系统最小的访问频次:minFreq

  4. 当缓存满时有数据k2需要插入,需要先O1寻找访问频次最低且插入最早的k1,然后删除它,接着O1更新k2的访问频次
    某个访问频次的k可能不止一个,有多个,如何O1找到这些k,用访问频次-集合的存储:freqTokeys
    如何从找到的集合中O1找到插入最早的k1,用双向链表,表头作为该频次中插入最早的元素。
    最终选择既有O1找到集合的map+O1找到插入最早的k1 -> HashMap<Integer, LinkedHashSet>

    LinkedHashSet类,链表和集合的结合体
    链表不能快速删除元素,但是能保证插入顺序
    集合内部元素无序,但是能快速删除元素(O(lgN))
    LinkedHashSet是一种在迭代其元素时可以返回它们被插入的顺序的set(集合类型)
    也就是说,它可以保证元素的插入与访问顺序。

private HashMap<K, V> keyToVal; // HashMap
private HashMap<K, Integer> keyToFreq; // HashMap
private int minFreq;
private int capacity;
private HashMap<Integer, LinkedHashSet<K>> freqTokeys;
public class LfuCache<K, V> {
    private HashMap<K, V> keyToVal;
    private HashMap<K, Integer> keyToFreq;
    private HashMap<Integer, LinkedHashSet<K>> freqTokeys;

    private int minFreq;
    private int capacity;

    public LfuCache(int capacity) {
        keyToVal = new HashMap<>();
        keyToFreq = new HashMap<>();
        freqTokeys = new HashMap<>();
        this.capacity = capacity;
        this.minFreq = 0;
    }

    public V get(K key) {
        V v = keyToVal.get(key);
        if (v == null) {
            return null;
        }
        // 如果k存在,则增加访问频次
        increaseFrey(key);
        return v;
    }

    public void put(K key, V value) {
        // get方法里面会增加频次
        if (get(key) != null) {
            // 重新设置值
            keyToVal.put(key, value);
            return;
        }

        // 超出容量,删除频率最低的key 【逐出策略】
        if (keyToVal.size() >= capacity) {
            removeMinFreqKey();
        }

		// 能进入到这里说明:最小访问频次一定是1
		// k-v插入
        keyToVal.put(key, value);
        // k-访问频次插入
        keyToFreq.put(key, 1);
        
        // freqTokeys中,key对应的value存在,返回存在的key;不存在,添加key和value
        // 不存在则创建一个新的LinkedHashSet并插入
        freqTokeys.putIfAbsent(1, new LinkedHashSet<>());
        // 访问频次为1的集合中,有序插入当前key
        freqTokeys.get(1).add(key);

		// 系统最小访问频次一定是1
        this.minFreq = 1;
    }

	// 【逐出策略】
    // 删除出现频率最低且插入最早的key
    private void removeMinFreqKey() {
    	// 找到最小访问频次对应的 LinkedHashSet<K> 集合&列表
        LinkedHashSet<K> keyList = freqTokeys.get(minFreq);
        // 获取keyList中的第一个元素
        // iterator()方法返回一个在一系列元素上进行迭代的迭代器
        // next()方法获取迭代器当前位置的下一个元素
        K deleteKey = keyList.iterator().next();
        
        // 从 keyList 中删除链表第一个节点,如果keyList中只有一个元素,则将整个keyList删除
        keyList.remove(deleteKey);
        if (keyList.isEmpty()) {
            // 这里删除元素后不需要重新设置minFreq,因为put方法执行完会将minFreq设置为1
            freqTokeys.remove(keyList);
        }
        
        // k-v中逐出
        keyToVal.remove(deleteKey);
        // k-访问频次中逐出
        keyToFreq.remove(deleteKey);
    }

    // 增加频率
    private void increaseFrey(K key) {
    	// 获取当前key的访问频次
        int freq = keyToFreq.get(key);
        // 当前key的访问频次+1
        keyToFreq.put(key, freq + 1);
        // 当前访问频次中维护的key集合中,删除当前key
        freqTokeys.get(freq).remove(key);
        // 当前访问频次+1中维护的key集合中,插入当前key(如果LinkedHashSet不存在,则先new一个)
        freqTokeys.putIfAbsent(freq + 1, new LinkedHashSet<>());
        freqTokeys.get(freq + 1).add(key);
        
        // 当前访问频次中维护的key集合为空,则remove掉该LinkedHashSet
        if (freqTokeys.get(freq).isEmpty()) {
            freqTokeys.remove(freq);
           
            // remove掉该LinkedHashSet,代表系统中最小的访问频次为 this.minFreq++
            if (freq == this.minFreq) {
                this.minFreq++;
            }
        }
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Android】数据安全(一) —— Sqlite加密

目录 SQLCipherSQLiteCrypt其它 SQLCipher SQLCipher 是 SQLite 数据库的的开源扩展&#xff0c;使用了 256 位 AES 加密&#xff0c;支持跨平台、零配置、数据100%加密、加密开销低至 5 -15%、占用空间小、性能出色等优点&#xff0c;因此非常适合保护嵌入式应用程序数据库&a…

238.除自身以外数组的乘积

题目&#xff1a;给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且…

八、软考-系统架构设计师笔记-系统质量属性和架构评估

1、软件系统质量属性 软件架构的定义 软件架构是指在一定的设计原则基础上&#xff0c;从不同角度对组成系统的各部分进行搭配和安排&#xff0c;形成系统的多个结构而组成架构&#xff0c;它包括该系统的各个构件&#xff0c;构件的外部可见属性及构件之间的相互关系。 软件架…

微信小程序购物/超市/餐饮/酒店商城开发搭建过程和需求

1. 商城开发的基本框架 a. 用户界面&#xff08;Frontend&#xff09; 页面设计&#xff1a;包括首页、商品列表、商品详情、购物车、下单界面、用户中心等。交云设计&#xff1a;如何让用户操作更加流畅&#xff0c;包括搜索、筛选、排序等功能的实现。响应式设计&#xff1…

洛谷 P8816 [CSP-J 2022] 上升点列(T4)

目录 题目传送门 算法解析 最终代码 提交结果 尾声 题目传送门 [CSP-J 2022] 上升点列 - 洛谷https://www.luogu.com.cn/problem/P8816 算法解析 k 0 且 xi, yi 值域不大时&#xff0c;这题是非常简单的 DP&#xff0c;类似「数字三角形」。 记 dp(x,y) 为「以 (x,y) …

笔记79:ROS入门之前的准备

一、ROS是什么 ROS其实是一个伪操作系统&#xff0c;是基于Liunx操作系统的一个用于机器人各个节点之间通信的系统&#xff1b;ROS制定了一系列规则使得每个节点之间遵循相同的通信规则&#xff0c;使得每个人都可以有一个守则区遵守开发自己的节点&#xff0c;也能和别人开发…

Exception异常处理

1. 两种异常处理机制 1.1 使用 throw 关键字手动抛出异常 使用throw关键字抛出异常&#xff0c;代码会的显得简单明了 如下图所示 1.2 使用 try-catch 捕获异常 使用try-catch进行捕获异常&#xff0c;往往会使代码变得更加笼统&#xff0c;层层包裹 如下图所示 2. 自定义…

从零学算法287

287.给定一个包含 n 1 个整数的数组 nums &#xff0c;其数字都在 [1, n] 范围内&#xff08;包括 1 和 n&#xff09;&#xff0c;可知至少存在一个重复的整数。 假设 nums 只有 一个重复的整数 &#xff0c;返回 这个重复的数 。 你设计的解决方案必须 不修改 数组 nums 且只…

聊聊python中面向对象编程思想

面向对象编程思想 1、什么是面向过程 传统的面向过程的编程思想总结起来就八个字——自顶向下&#xff0c;逐步细化&#xff01; → 将要实现的功能描述为一个从开始到结束按部就班的连续的“步骤” → 依次逐步完成这些步骤&#xff0c;如果某一个步骤的难度较大&#xff…

2024年品牌推广:构建品牌生态圈与注重品牌故事和文化传播

在全球经济深度融合、数字化浪潮汹涌澎湃的2024年&#xff0c;品牌推广的策略与模式正经历着前所未有的变革。在这一背景下&#xff0c;构建品牌生态圈和注重品牌故事与文化传播&#xff0c;成为了企业提升品牌竞争力和市场占有率的重要手段。 一、2024年市场经济分析与现状 …

上门预约按摩系统相比较传统按摩店有哪些优点和特色;

上门按摩系统与传统按摩店的运营对比&#xff1a; 1. 技师自由选择&#xff1a;在上门按摩系统中&#xff0c;技师可以兼职加入&#xff0c;无需固定门店。平台为技师提供订单&#xff0c;技师则携带基础服务用具上门服务。同时&#xff0c;兼职技师也需提交详尽资料和资质证明…

伟骅英才|二月二:龙年龙抬头

二月二龙抬头&#xff0c;是中国民间传统节日&#xff0c;人们期盼通过对龙的祈求来实现降雨的目的&#xff0c;寄托了老百姓对美好生活的向往。这一天&#xff0c;人们通常会去理个发&#xff0c;寓意着“二月二剃龙头&#xff0c;一年都有精神头”。现如今的二月二&#xff0…

软件测试需要学什么?学多久?软件测试技术进阶路线图

很多新手&#xff0c;不知道软件测试学习该如何开始&#xff0c;软件测试需要掌握哪些知识。下面是根据本人的理解&#xff0c;粗略整理的一个学习大纲&#xff0c;基本上涵盖了软件测试工程师需要掌握的全部技能&#xff0c;希望对刚入行或者准备学习测试的朋友提供一点指引。…

Java17 --- SpringCloud初始项目创建

目录 一、cloud项目创建 1.1、项目编码规范 1.2、注解生效激活 1.3、导入父工程maven的pom依赖 二、创建子工程并导入相关pom依赖 2.1、相关配置文件 2.1.1、数据库配置文件内容 2.1.2、自动生成文件配置内容 三、创建微服务8001子工程 3.1、导入相关pom依赖 3.…

基于51单片机超声波测距

目录 摘 要 2 ABSTRACT 3 目 录 4 1 绪论 1 1 概述 12 国内外发展现状 1 2 系统总体方案设计 21 设计要求 2 1&#xff09;可进行距离测量。 2 2&#xff09; 采用数码管显示距离数据。 2 3&#xff09; 可按键设置距离门限值 2 4&#xff09; 具有报警功能 22 方案选择 2 1 …

Vue点击切换组件颜色

例如我有一个这样的组件&#xff0c;我希望在点击组件之后由蓝色变成橙色 先把原来的代码附上(简化掉了叉号&#xff09;&#xff1a; <div v-for"(item, index) in words" :key"index" class"scrollbar-demo-item"><span>{{ item …

PL/SQL学习笔记

介绍 PL/SQL 编程语言是SQL 和 Oracle 关系数据库的过程扩展语言 是Oracle 编程环境中的一个工具 基本语法 S.No Sections & Description 1 Declarations 此部分以关键字 DECLARE 开头。 它是一个可选部分&#xff0c;定义了程序中要使用的所有变量、游标、子程序和其他…

C++虚继承的一些细节

C虚继承的一些细节 何时使用虚继承普通继承的类对象布局虚继承类对象布局虚函数表指针虚函数表内容 何时使用虚继承 看代码&#xff0c;代码主要是菱形继承&#xff0c;base里面的成员变量会存在二义性 #include<iostream> using namespace std;class base { public:in…

客户案例|100M 768 维向量数据,Zilliz Cloud 稳定支持 Shulex VOC 业

日前&#xff0c;国际化 VOC SaaS 公司数里行间&#xff08;Shulex&#xff09;将上亿数据量的核心业务从开源向量数据库 Milvus 迁移至全托管的向量数据库云服务 Zilliz Cloud。 相比于 Milvus&#xff0c;Zilliz Cloud 实现了 Shulex VOC 评论分析洞察报告生成速度 30% 的提升…

第二十天-数据分析

1.介绍 1.什么是数据分析 1.以下4个纬度结合起来的数据科学 2.数据分析的特殊性