【Redis】缓存预热、雪崩、击穿、穿透、过期删除策略、内存淘汰策略
Redis常见问题总结:
- Redis常见问题总结
- Redis缓存预热
- Redis缓存雪崩
- Redis缓存击穿
- Redis缓存穿透
- Redis 中 key 的过期删除策略
- 数据删除策略
- Redis内存淘汰策略
- 一、Redis对过期数据的处理
- (一)相关配置
- (二)内存淘汰流程
- (三)动态改配置命令
- 二、内存淘汰策略的种类及特点
- (一)Redis 4.0以前的策略
- (二)Redis 4.0以后增加的策略
- 三、常见的淘汰算法
- (一)FIFO算法(先进先出)
- (二)LRU算法(最近最少使用)
- (三)LFU算法(最不常使用)
- (四)LRU和LFU的选择
- 总结
Redis常见问题总结
Redis缓存预热
“宕机”服务器启动后迅速宕机,指的是服务刚上线由于Redis中没有任何数据,导致大量请求访问数据库,主从之间数据吞吐量较大,数据同步操作频度较高。
而缓存预热解决的就是,在系统启动前,提前将相关的数据直接加载到缓存系统。避免用户在请求的时候,先查询数据库,再将数据库的查询到的数据缓存到Redis的问题。用户可以直接查询事先被预热的缓存数据。
解决方案:
- 准备工作:
- 日常例行统计数据访问记录,统计访问频度较高的热点数据。
- 将统计结果中的数据分类,根据级别,Redis优先加载级别较高的热点数据
- 实施:
- 使用脚本程序固定触发数据预热过程
- 如果条件允许,使用CDN(内容分发网络),效果会更好
Redis缓存雪崩
缓存雪崩是指在同一时段大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,带来巨大压力。【这里指的是同一批key的过期时间相同或者Redis服务挂掉】
解决方案:
- 给不同的Key的TTL添加随机值
- 利用Redis集群提高服务的可用性
- 给缓存业务添加降级限流策略
- 给业务添加多级缓存
Redis缓存击穿
缓存击穿问题也叫热点Key问题,就是一个被高并发访问并且缓存重建业务较复杂的key突然失效了,无数的请求访问会在瞬间给数据库带来巨大的冲击
常见的解决方案有两种:
- 互斥锁
- 逻辑过期
互斥锁:
逻辑过期:
Redis缓存穿透
缓存穿透是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会生效,这些请求都会打到数据库
常见两种解决方案:
- 缓存空对象
- 布隆过滤器
Redis 中 key 的过期删除策略
数据删除策略
什么是过期数据?
Redis是一种内存级数据库,所有数据均存放在内存中,内存中的数据可以通过TTL指令获取其状态
- XX :具有时效性的数据
- -1 :永久有效的数据
- -2 :已经过期的数据或被删除的数据或未定义的数据
注意:过期的数据真的删除了吗?不是的
删除策略比对
1. 定时删除 节约内存,无占用 不分时段占用CPU资源,频度高拿时间换空间
2. 惰性删除 内存占用严重延时执行,CPU利用率高拿空间换时间
3. 定期删除 内存定期随机清理每秒花费固定的CPU资源维护内存随机抽查,重点抽查
Redis的过期键的删除策略是指当Redis中的缓存的key过期了,Redis要如何处理。
Redis中提供了三种删除策略:
1.定时删除
当放入数据后,设置一个定时器,当定时器读秒完毕后,将对应的数据从dict中删除。
优点: 内存友好,数据一旦过期就会被删除
缺点: CPU不友好,定时器耗费CPU资源,并且频繁的执行清理操作也会耗费CPU资源。用时间换空间
2.惰性删除
当数据过期的时候,不做任何操作。当访问数据的时候,查看数据是否过期,如果过期返回null,并且将数据从内存中清除。如果没过期,就直接返回数据。
优点: CPU友好,数据等到过期并且被访问的时候,才会删除。
缺点: 内存不友好,会占用大量内存。用空间换时间
3.定期删除
定期删除是定时删除和惰性删除的折中方案。每隔一段时间对redisServer中的所有redisDb的expires依次进行随机抽取检查。
Redis中有一个server.hz定义了每秒钟执行定期删除的次数,每次执行的时间为250ms/server.hz。Redis中会维护一个current_db变量来标志当前检查的数据库。current_db++,当超过数据库的数量的时候,会重新从0开始。
定期检查就是执行一个循环,循环中的每轮操作会从current_db对应的数据库中随机依次取出w个key,查看其是否过期。如果过期就将其删除, 并且记录删除的key的个数。如果过期的key个数大于w25%,就会继续检查当前数据库,当过期的key小于w25%,会继续检查下一个数据库。当执行时间超过规定的最大执行时间的时候,会退出检查。一次检查中可以检查多个数据库,但是最多检查数量是redisServer中的数据库个数,也就是最多只能从当前位置检查一圈。
Redis内存淘汰策略
一、Redis对过期数据的处理
Redis的内存淘汰机制主要是用于在Redis用于缓存的内存不足时,处理需要新写入且需申请额外空间的数据。
(一)相关配置
- 在
redis.conf
中:- 配置
maxmemory <bytes>
,用于设置Redis的最大内存空间。若不设定该参数,默认无限制,通常会设定为物理内存的四分之三。 - 配置
maxmemory-policy noeviction
,用于设置淘汰策略,默认为noeviction
。
- 配置
(二)内存淘汰流程
- 客户端发起需要申请更多内存的命令(如
set
)。 - Redis检查内存使用情况,若已使用内存大于
maxmemory
,则根据用户配置的不同淘汰策略来淘汰内存(key),以换取一定的内存。 - 若上述步骤均无问题,则该命令执行成功。
(三)动态改配置命令
Redis支持动态改配置,无需重启。
- 设置最大内存:
config set maxmemory 100000
- 设置淘汰策略:
config set maxmemory-policy noeviction
二、内存淘汰策略的种类及特点
(一)Redis 4.0以前的策略
- noeviction:当内存使用超过配置时会返回错误,不会驱逐任何键。(默认选项,一般不选用)
- allkeys-lru:当内存不足以容纳新写入数据时,在整个键空间中,移除最近最少使用的key。(最常用)
- volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用的key。
- allkeys-random:当内存不足以容纳新写入数据时,在整个键空间中,随机移除某个key。
- volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某个key。
- volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的key优先移除。
(二)Redis 4.0以后增加的策略
- volatile-lfu:从所有配置了过期时间的键中驱逐使用频率最少的键。
- allkeys-lfu:从所有键中驱逐使用频率最少的键。
内存淘汰策略可通过配置文件修改,redis.conf
对应的配置项是maxmemory-policy
,修改对应的值即可。
三、常见的淘汰算法
(一)FIFO算法(先进先出)
- 思想
- 基于队列的先进先出原则,最先进入的数据会被最先淘汰掉,是最简单、最公平的思想。
- 实现
- 维护一个FIFO队列,按照时间顺序将各数据(已分配页面)链接起来组成队列,并将置换指针指向队列的队首。进行置换时,把置换指针所指的数据(页面)顺次换出,并把新加入的数据插到队尾即可。
- 缺点
- 会导致缺页率增加。随着分配页面的增加,被置换的内存页面往往是被频繁访问的,因此FIFO算法会使一些页面频繁地被替换和重新申请内存,从而导致缺页率增加。由于缺页率会随着分配页面的增加而增加,使得redis的开销也逐渐增加,所以这种算法已不再使用。
(二)LRU算法(最近最少使用)
- 思想
- 最近最少使用的会被优先淘汰。如果一个数据在最近一段时间没有被访问到,那么在将来它被访问的可能性也很小。当空间满时,最久没有访问的数据最先被淘汰掉。
- 实现
- 用双向链表(LinkedList)+哈希表(HashMap)实现(链表用来表示位置,哈希表用来存储和查找),在Java里有对应的数据结构
LinkedHashMap
。
- 用双向链表(LinkedList)+哈希表(HashMap)实现(链表用来表示位置,哈希表用来存储和查找),在Java里有对应的数据结构
- 缺点
- 在需要淘汰时,只是随机选取有限的key进行对比,排除掉访问时间最久的元素,不能选择整个候选元素的最优解,只是局部最优。默认随机选取的key的数目为5,在配置文件
redis.conf
中由maxmemory_samples
属性的值决定,采样数量越大越接近于标准LRU算法,但也会带来性能的消耗。 - 在Redis 3.0以后增加了LRU淘汰池,进一步提高了与标准LRU算法效果的相似度。淘汰池即维护的一个数组,数组大小等于抽样数量
maxmemory_samples
,在每一次淘汰时,新随机抽取的key和淘汰池中的key进行合并,然后淘汰掉最旧的key,将剩余较旧的前面5个key放入淘汰池中待下一次循环使用。假如maxmemory_samples = 5
,随机抽取5个元素,淘汰池中还有5个元素,相当于变相的maxmemory_samples = 10
,所以进一步提高了与LRU算法的相似度。
- 在需要淘汰时,只是随机选取有限的key进行对比,排除掉访问时间最久的元素,不能选择整个候选元素的最优解,只是局部最优。默认随机选取的key的数目为5,在配置文件
(三)LFU算法(最不常使用)
- 思想
- 如果一个数据在最近一段时间很少被访问到,那么在将来它被访问的可能性也很小。当空间满时,最小频率访问的数据最先被淘汰。
- 实现及问题解决
- 为每个key维护一个计数器,每次key被访问时,计数器增大,计数器越大,则认为访问越频繁。但存在以下问题:
- 可能存在某个key在开始一个小时内有100万的访问量,但之后一小时内访问量为0,而在第二个小时内另一个key的访问量达到20万,此时第二个小时内key1会优先于key2被淘汰,尽管key2在该小时内访问量更大。
- 当新加入的key,由于没有被访问过,初始计数器为0,若此时触发淘汰机制,会把最先添加的key最先淘汰掉。
- 解决方案:在LFU算法中维护了一个24bit的字段,被分成16 bits与8 bits两部分。第一部分(高16 bits)用来记录计数器的上次缩减时间,时间戳,单位精确到分钟。第二部分(低8 bits)用来记录计数器的当前数值,该数值反映访问频率,而非次数。
- 在
redis.conf
配置文件中,lfu-log-factor
用来调整计数器counter的增长速度,lfu-log-factor
越大,counter增长越慢。lfu-decay-time
是一个以分钟为单位的数值,用来调整counter的缩减速度。
- 为每个key维护一个计数器,每次key被访问时,计数器增大,计数器越大,则认为访问越频繁。但存在以下问题:
(四)LRU和LFU的选择
需要根据业务权衡到底是选择淘汰最近最少使用(LRU)还是选择最不经常使用(LFU)。总的来说,无论是LRU、LFU、TTL还是Random都是近似算法来实现的,在可靠性和性能上做了一定的平衡。在业务中应主动删除没有价值的数据,或者更新某些key的过期时间等来提高Redis的性能和空间,不能过分依赖于淘汰策略。
(此处可根据需要插入相关图片,例如LRU和LFU算法的示意图等,假设插入了一张LRU算法的示意图,如下所示)
总结
Redis的内存淘汰策略的选取并不会影响过期的key的处理。内存淘汰策略用于处理内存不足时需要申请额外空间的数据;过期策略用于处理过期的缓存数据。要根据实际业务场景和需求合理选择内存淘汰策略,并结合主动的数据管理操作来优化Redis的性能和内存使用。
相关文章:

【Redis】缓存预热、雪崩、击穿、穿透、过期删除策略、内存淘汰策略
Redis常见问题总结: Redis常见问题总结Redis缓存预热Redis缓存雪崩Redis缓存击穿Redis缓存穿透 Redis 中 key 的过期删除策略数据删除策略 Redis内存淘汰策略一、Redis对过期数据的处理(一)相关配置(二)内存淘汰流程&a…...

【LeetCode】每日一题 2024_10_15 三角形的最大高度(枚举、模拟)
前言 每天和你一起刷 LeetCode 每日一题~ LeetCode 启动! 题目:三角形的最大高度 代码与解题思路 久违的简单题 这道题读完题目其实不难想到有两条路可以走: 1、题目很明显只有两种情况,枚举是第一个球是红球还是蓝球这两种情…...

2024版最新网络安全工程师入门教程(非常详细)从零基础入门到精通,看完这一篇就够了
前言 想要成为网络安全工程师,却苦于没有方向,不知道从何学起的话,下面这篇 网络安全入门 教程可以帮你实现自己的网络安全工程师梦想,如果想学,可以继续看下去,文章有点长,希望你可以耐心看到…...
vue中关于router.beforeEach()的用法
router.beforeEach()是Vue.js中的路由守卫,用于在路由跳转前进行校验、取消、重定向等操作。 基本使用: const router new VueRouter({ ... })router.beforeEach((to, from, next) > {// ... }) to: 即将要进入的目标路由对象 from: 当前导航正要…...

C++模板初阶,只需稍微学习;直接起飞;泛型编程
🤓泛型编程 假设像以前交换两个函数需要,函数写很多个或者要重载很多个;那么有什么办法实现一个通用的函数呢? void Swap(int& x, int& y) {int tmp x;x y;y tmp; } void Swap(double& x, double& y) {doubl…...

【数据结构 | 红黑树】红黑树的性质和插入结点时的调整
文章目录 红黑树红黑树插入时的调整?1. 插入结点是根结点2. 插入结点的叔叔是红色3. 插入结点的叔叔是黑色LL 型RR型LR型RL型 红黑树 前提:二叉搜索树(左 < 根 < 右)—— 左根右根和**叶子(NULL)**都…...
mysql学习教程,从入门到精通,SQL导入数据(44)
1.SQL 导出数据 以下是一个关于如何使用 SQL 导出数据的示例。这个示例将涵盖从一个关系数据库管理系统(如 MySQL)中导出数据到 CSV 文件的基本步骤。 1.1、前提条件 你已经安装并配置好了 MySQL 数据库。你有访问数据库的权限。你知道要导出的表名。…...

【SpringAI】(二)让你的Java程序接入大模型——适合Java宝宝的大模型应用开发
开始之前,如果你对大模型完全没了解过,建议阅读之前的大模型入门文章: 【SpringAI】(一)从实际场景入门大模型——适合Java宝宝的大模型应用开发 那么今天就开始写一个基于Spring AI程序的HelloWord!将大模型接入到咱…...

音频剪辑在线工具 —— 让声音更精彩
你是否曾梦想过拥有自己的声音创作空间,却苦于复杂的音频编辑软件?接下来,让我们一同揭开这些音频剪辑在线工具的神秘面纱,看看它们如何帮助你实现从录音到发布的无缝衔接。 1.福昕音频剪辑 链接直达>>https://www.foxits…...
http短连接和长连接
参考短连接和长连接 短连接:客户端向服务器每进行一次Http操作,都需建立一次连接,任务完成后,断开连接;长连接:建立长连接后,传输数据的连接将不会中断,客户端每次访问服务器时都会…...
日志分析删除
日志分析 场景 运维嫌弃生产环境打印日志过多,而且日志存储需要费用,让我们减少打印日志大小,所以需要分析日志在哪里打印的过多 解决方案 读取生产日志文件,统计分析打印日志的地方,最后删除代码中打印日志的地方…...

DART: Implicit Doppler Tomography for Radar Novel View Synthesis 笔记
Link:https://wiselabcmu.github.io/dart/ Publish: 2024CVPR Abstract DART主要任务就是用来合成雷达距离多普勒图像range-droppler,可用于生成高质量的断层扫描图像。 Related Work 1 Radar Simulation 基于模型的方法 任务ÿ…...
redis-cli执行lua脚本
连接redis服务器命令 redis-cli -h 10.10.xx.xx -p 6380 -a password执行lua脚本传递KEY VALUE redis-cli -h 10.10.xx.xx -p 6380 -a password key1 key2 , arg1 arg2key和参数通过逗号分割,逗号前后必须有一个空格 如下执行lua脚本示例: -- script.…...

MySQL9的3个新特性
【图书推荐】《MySQL 9从入门到性能优化(视频教学版)》-CSDN博客 《MySQL 9从入门到性能优化(视频教学版)(数据库技术丛书)》(王英英)【摘要 书评 试读】- 京东图书 (jd.com) 本文讲解MySQL9的3个新特性&…...
《网络基础之 HTTP 协议:状态码含义全解析》
《网络基础之 HTTP 协议:状态码含义全解析》 在网络通信的浩瀚世界中,HTTP 协议犹如一座坚实的桥梁,连接着客户端与服务器。而其中的状态码,则是这座桥梁上的重要标识,为双方的交互提供了关键的反馈信息。 一、状态码…...

java真的正在越来越失去竞争力了吗
题记: java真的在越来越失去竞争力了吗?最近参加校招面试,过程中有问道java的问题,有的同学很直接了当(或者是不假思索)地说,java已经过时了吧,现在学java的人越来越少了。那么事实…...

【通过zip方式安装mysql服务】
通过zip方式安装mysql服务 Mysql安装包下载mysql安装及环境配置1.解压缩配置环境变量初始化mysql配置安装mysql服务启动MySQL服务连接mysql修改root用户密码 Mysql安装包下载 通过访问mysql官网下载:mysql下载地址 mysql安装及环境配置 1.解压缩 下载完成后&am…...

每日OJ题_WY3小易的升级之路_数学模拟_C++_Java
目录 牛客_WY3小易的升级之路_数学模拟 题目解析 C代码 Java代码 牛客_WY3小易的升级之路_数学模拟 小易的升级之路_牛客题霸_牛客网 (nowcoder.com) 描述: 小易经常沉迷于网络游戏.有一次,他在玩一个打怪升级的游戏,他的角色的初始能力值为 a.在接下来的一段…...
python xml的读取和写入
import xml.etree.ElementTree as ET from xml.dom import minidom# 读取XML文档 tree ET.parse("./xml_3/z_20240827_001.xml") root tree.getroot() # 获取size元素 size_find_0 root.find("size") # 获取width子元素 size_w size_find_0.find("…...

WebGL 小白入门学习
1. WebGL是什么? WebGL(Web Graphics Library)是一种JavaScript API,它允许你在不需要安装任何额外插件的情况下,直接在浏览器中渲染高性能的2D和3D图形。WebGL利用了用户的图形处理单元(GPU)来…...
论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)
HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...

Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具
文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
比较数据迁移后MySQL数据库和OceanBase数据仓库中的表
设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...

LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...