Redis——缓存

目录
·前言
一、缓存基本概念
1.概念
2.二八定律
二、使用 Redis 作为缓存
三、缓存的更新策略
1.定期生成
2.实时生成
四、Redis 内存淘汰机制
1.通用淘汰策略
(1)FIFO
(2)LRU
(3)LFU
(4)Random
2.Redis 内置的淘汰策略
(1)volatile-lru
(2)allkeys-lru
(3)volatile-lfu
(4)allkeys-lfu
(5)volatile-random
(6)allkeys-random
(7)volatile-ttl
(8)noeviction
五、缓存使用的注意事项
1.缓存预热(Cache preheating)
2.缓存穿透(Cache penetration)
3.缓存雪崩(Cache avalanche)
4.缓存击穿(Cache breakdown)
·结尾
·前言
我们都知道 Redis 的主要用途有三个方面:存储数据、作为缓存和消息队列,其中,Redis 最常用的场景就是作为缓存了,本篇文章就来和大家介绍一下缓存的基本概念,如何使用 Redis 作为缓存,缓存的更新策略有哪些,Redis 中的内存淘汰机制是怎样的,还有关于使用缓存的一些注意事项,那么就开始本篇文章的正题吧。
一、缓存基本概念
1.概念
相信大家都有过坐火车的经历,在我们坐火车时会带着一个拉杆箱,这个拉杆箱可以装很多很多的东西,如果我们把所有东西都放在了拉杆箱中,就会遇见一个问题:在我们进入火车站时,需要刷身份证进站,由于你把所有东西都放在了拉杆箱中,此时你就需要把拉杆箱放倒在地上,打开拉杆箱,翻找身份证,刷身份证进站,再把身份证放回拉杆箱,这一系列的繁琐过程结束后,才算是用身份证进入了车站,但是在后面需要刷身份证检票时、刷身份证出站时,在火车上列车员需要用身份证检验时,你都要重复上述取身份证的过程,这种方式就十分低效了,那么怎么做可以更高效呢,我想大家都是知道的,就是把身份证、手机之类经常需要使用的都放在衣服兜中,这样使用起来就会更加方便,高效。
看完上面的例子,其实我们说的缓存做的事情就类似于我们衣服兜起到的效果,缓存是计算机中的一个经典概念,其核心思路就是把一些常用的数据放到触手可及的地方,方便随时读取,在我们的计算机上,各个硬件读取速度快慢有以下的顺序:
CPU 寄存器 > 内存 > 硬盘 > 网络
速度快的设备可以作为速度慢的设备的缓存,那么我们就可以使用内存来作为硬盘的缓存,这也是 Redis 主要的用途,还可以使用硬盘来作为网络的缓存,比如浏览器中的缓存。
2.二八定律
既然缓存读取速度更快,那为什么不都用缓存来存储数据呢?这是因为缓存的内存空间往往是不足的,所以大部分情况下,缓存只是放一些热点数据(访问频繁的数据),缓存存在的意义一是因为它读取速度快,二就是因为“二八定律”。
二八定律的意思是,我们 20% 的热点数据能够应付 80% 的访问场景,所以我们只需要把这少量的热点数据放到缓存中,就可以应对大多数的场景,从而在整体上有明显的性能提升。
二、使用 Redis 作为缓存
在我们实际应用中,通常会使用 Redis 作为 Mysql 的缓存,虽然关系型数据库(Mysql)的功能强大,但是它有着一个很大的缺陷,就是性能不高,为什么性能不高,大致有以下几点原因(关系型数据库就以 MySql 为例):
- MySql 把数据存储在硬盘上,硬盘上的 IO 速度并不快,尤其是在随机访问时;
- 使用 MySql 进行查询过程中,如果查询不能命中索引,就需要进行表的遍历,这会大大的增加硬盘 IO 的次数;
- MySql 对于 SQL 在执行会做一系列的解析、校验、优化的工作;
- 如果使用 MySql 做一些复杂查询,比如:多表联合查询,需要使用笛卡尔积进行操作,效率会降低很多。
因为 MySql 等数据库有着上面的问题,所以承担的并发量就有限,一旦请求的数量多了,数据库的压力就会很大,就可能会宕机,那么如何提高 MySql 能承担的并发量呢?有以下两种方案可以做到:
- 开源:引入更多的机器,构成数据库集群;
- 节流:引入缓存,把一些频繁读取的热点数据保存到缓存中,这样后续在查询数据的时候,先在缓存中查询,如果缓存中已经存在就不再访问 MySql 了。
Redis 就是作为数据库缓存的常见方案,关于 Redis 可以作为 Mysql 缓存有以下两种原因:
- Redis 数据在内存中,访问内存速度比访问硬盘快很多;
- Redis 只是支持简单的 key-value 存储,不涉及复杂的查询的诸多限制规则。
此时当 Redis 作为 MySql 的缓存后,他们的关系,可以形象的如下图所示:
Redis 就像盾牌一样会先接收大部分的请求,少部分 Redis 上没有的数据才会请求 MySql。
注意:只有在进行读操作时,使用 Redis 作为缓存才有作用,如果进行的是写操作,那还是要对 MySql进行操作的
三、缓存的更新策略
通过上面的介绍,我们知道引入缓存的意义是用来存一些热点数据,并配合二八定律可以很好的分担 Mysql 的压力,可是什么数据是“热点数据”呢?对于存储的热点数据就有以下两种生成方式,下面来展开介绍一下这两种方式。
1.定期生成
定期生成这种策略,就是每隔一定的周期(比如一天/一周/一个月),对访问数据的频次进行统计,挑选出访问频次最高的前 N%来存储在缓存中。
使用这种策略的优缺点如下:
- 优点:定期生成的策略实现起来比较简单,过程可控,方便排查问题;
- 缺点:实时性不够,如果出现一些突发事件,有一些本来不是热词的内容突然成为了热词,新的热词就可能就数据库带来较大的压力。
关于上述缺点中的实时性有一个很好的例子,那就是在过年时搜索“春节晚会”的时候,这个词一般只会在过年期间会被人们进行搜索,并且搜索量巨大,此时由于定期生成周期还没有进行更新,就会造成这些搜索请求直接访问后面的数据库了。
2.实时生成
为了弥补上述定期生成策略的缺点,实时生成会采用动态生成热点数据的方式,我们首先需要给缓存设定容量上限(在 Redis 配置文件中的 maxmemory 参数可以设定容量上限),接下来用户的每次查询操作就会经历以下的步骤:
- 如果在 Redis 中查找到,就直接返回;
- 如果 Redis 中不存在,就从数据库中查,把查到的结果同时也写入到 Redis中。
此时,经过一段时间的“动态平衡”,Redis 中的数据就都成了热点数据了,但是同时也有一个问题,就是这样不停的往 Redis 中写数据,会导致 Redis 中的内存占用越来越多,逐渐达到内存的上限,这就出现不能继续存数据了的问题,那么针对这种问题,Redis 中有着内存淘汰这样的机制。
四、Redis 内存淘汰机制
为了解决实时生成策略引发内存满如何继续存储数据的问题,Redis 就引入了“内存淘汰”这样的机制,在介绍 Redis 的淘汰机制之前,先来介绍一些通用的淘汰策略。
1.通用淘汰策略
(1)FIFO
FIFO 的英文全称是 First In First Out 意思是先进先出,这种策略是把缓存中存在时间最久的(也就是最先来的数据)淘汰掉,然后添加新的数据。
(2)LRU
LRU 的英文全称是 Least Recently Used 意思是淘汰最近未使用的,此时,在缓存中记录每个数据最近访问的时间,把最近访问时间最老的数据淘汰掉,然后添加新的数据。
(3)LFU
LFU 的英文全称是 Least Frequently Used 意思是淘汰访问次数最少的,此时,在缓存中记录每条数据最近一段时间的访问次数,把访问次数最少的数据淘汰掉,然后添加新的数据。
(4)Random
Random 是随机淘汰的意思,这种策略会在缓存中所有的数据中随机抽取幸运儿来淘汰掉,然后再添加新的数据。
2.Redis 内置的淘汰策略
(1)volatile-lru
这种策略是当内存不足以容纳新写入的数据时,从设置了过期时间中的 key 中使用 LRU (最近最少使用)算法进行淘汰。
(2)allkeys-lru
这种策略是当内存不足以容纳新写入的数据时,从所有 key 中使用 LRU(最近最少使用)算法进行淘汰。
(3)volatile-lfu
这种策略是在 Redis 4.0 版本新增的,当内存不足以容纳新写的数据时,在过期的 key 中,使用 LFU(访问次数最少)算法进行淘汰。
(4)allkeys-lfu
这种策略是 Redis 4.0 版本新增的,当内存不足以容纳新写的数据时,从所有 key 中,使用 LFU(访问次数最少)算法进行淘汰。
(5)volatile-random
这种策略是当内存不足以容纳新写入的数据时,从设置了过期时间的 key 中,随机淘汰数据。
(6)allkeys-random
这种策略是当内存不足以容纳新写入的数据时,从所有的 key 中,随机淘汰数据。
(7)volatile-ttl
这种策略是在设置了过期时间的 key 中,根据过期时间进行淘汰,越早过期的优先被淘汰(相当于 FIFO 算法,只不过是局限于设置过期时间的 key)
(8)noeviction
这种策略是 Redis 默认策略,当内存不足以容纳新写入的数据时,新写入数据就会报错。
通过上述 Redis 中内置的淘汰策略的介绍,可以看出,Redis 默认策略不适合于实时更新缓存,以上的在 Redis 中有一个配置项,就可以设置 Redis 采取上述那种策略淘汰内存数据。至于采取哪种策略更好,就需要具体问题具体分析了。
五、缓存使用的注意事项
1.缓存预热(Cache preheating)
当我们是首次将 Redis 服务器接入整个系统来作为缓存时,Redis 服务器中是没有数据的,此时如果我们的缓存更新策略是采用定期生成的方式,就不会涉及缓存预热,但是如果我们使用的是实时生成,就会出现以下问题:
由于 Redis 服务器是首次接入,其内部没有数据,此时按照实时生成策略,客户端会先查询 Redis,如果没有查到就会再查一次 Mysql,查到之后再把数据写入到 Redis 中,在这个过程中,所有的请求就会都打给 MySql,此时的请求如果过多就会给 MySql 造成很大的压力。
缓存预热就是用来解决上述问题的,它的解决方式就是将定期生成与实时生成的两种策略进行结合,先在 Redis 服务器没有上线的时候通过统计,将热点数据找到一批,然后导入 Redis 中,此时导入的这批热点数据就可以帮 MySql 承担很大的压力,随着时间推移,Redis 中就逐渐使用新的热点数据淘汰掉旧的热点数据了。
2.缓存穿透(Cache penetration)
缓存穿透就是在查询某个 key 时,这个 key 在 Redis 中没有,MySql 中也没有,此时,由于 MySql 中也没有这个 key ,这条 key 就不会被更新到 Redis 中,但是如果出现很多这样的数据被查询,并且反复查询,请求就会全都打给 Mysql 此时就会给 MySql 带来很大的压力。出现这种问题的原因有以下几条:
- 代码设计不合理,比如缺少必要的参数校验环节,导致非法的 key 也被进行查询了;
- 在开发过程中,不小心把部分数据从数据库中误删了;
- 遭到黑客的恶意攻击。
那么如何解决缓存穿透这样的问题呢?有以下几个解决方案:
- 针对要查询的参数进行严格的合法性校验;
- 针对 Redis 和 Mysql 中都不存在的 key 仍写入到 Redis 中,将这里的 value 也设成一个非法值(比如“”);
- 引入 布隆过滤器,在每次查询 Redis/MySql 之前都先判定一下 key 是否在 布隆过滤器 上存在(把所有 key 都插入到 布隆过滤器 中)。
上述解决方法中的 布隆过滤器 是一种本质上结合了 hash 与 bitmap 的数据结构,它可以以比较小的空间开销,比较快的时间速度来实现针对 key 是否存在做出判定。
3.缓存雪崩(Cache avalanche)
缓存雪崩就是指在短时间内,Redis 上大规模的 key 失效,导致缓存命中率陡然下降,并且 MySql 的压力迅速上升,导致 MySql 直接宕机。出现这个问题的原因有主要两种:
- Redis 服务器宕机 / Redis 集群模式下大量的节点宕机;
- Redis 没有问题,但是由于之前短时间内设置的很多 key 它们的过期时间是相同的。
那么如何解决这种问题呢? 有以下几种解决方案:
- 增加并完善报警体系,争取在第一时间发现 Redis 服务器宕机;
- 部署高可用的 Redis 集群;
- 不给 key 设置过期时间 / 设置过期时间的时候添加随机的因子(避免同一时刻过期)。
4.缓存击穿(Cache breakdown)
缓存击穿可以看作缓存雪崩的特殊情况,是指热点 key 突然过期了,导致大量的请求直接访问到 MySql 中,使 MySql 服务器压力骤增甚至宕机。
解决这种问题的方式有以下几种:
- 基于统计的方式发现热点 key 并且设置永不过期;
- 进行必要的服务降级,例如访问 Mysql 的时候使用分布式锁,限制同时请求 MySql 的并发数。
·结尾
文章到此就要结束了,关于 Redis 作为缓存的意义,更新缓存中实时生成时需要用到的淘汰策略,以及在使用 Redis 作为缓存时需要注意的一些事项介绍的也差不多了,本篇文章以文字为主,希望大家可以很好的理解其中的内容,如果本篇文章对你有所帮助还是希望能得到你的三连支持咯~~如果对文章内容有什么问题,欢迎在评论区进行留言讨论,我们下一篇文章再见~~~
相关文章:
Redis——缓存
目录 前言 一、缓存基本概念 1.概念 2.二八定律 二、使用 Redis 作为缓存 三、缓存的更新策略 1.定期生成 2.实时生成 四、Redis 内存淘汰机制 1.通用淘汰策略 (1)FIFO (2)LRU (3)LFU &#…...
RHCSA笔记三
第二章 linux中执行命令 命令格式 命令分为两类 内置命令:由 shell 程序自带的命令 外部命令:有独立的可执行程序文件,文件名即命令名 格式 主命令 参数 操作对象 # 注意: 下面是对于命令的语法的一些符号的说明࿱…...
【python】sorted() list.sort()
文章目录 sorted()和list.sort()sorted 函数sorted()根据键对字典排序根据字典的键排序根据字典的值排序将排序结果转换回字典 list.sort() 方法总结 keylambda student: student[age] sorted()和list.sort() 在Python中,sorted 函数和 list.sort() 方法都可以用来…...
训练集alpaca、sharegpt格式
LLaMA-Factory微调支持的格式 支持 alpaca 格式和 sharegpt 格式的数据集。 Alpaca格式 格式: [{"instruction": "人类指令(必填)","input": "人类输入(选填)","output": "模型回答(必填)","syst…...
Hive的数据存储格式
目录 一、前言 二、存储格式 2.1、文本格式(TextFile) 2.1.1、定义与特点 2.1.2、存储与压缩 2. 1.3、使用场景 2.2、行列式文件(ORCFile) 2.2.1、ORC的结构 2.2.2、ORC的数据类型 2.2.3、ORC的压缩格式 2.2.3、ORC存储…...
Linux Rsyslog 配置
1、Linux Rsyslog客户端配置 1)安装rsyslog yum install rsyslog 2)启用TCP或UDP传输 vim /etc/rsyslog.conf# Provides UDP syslog reception #若启用UDP进行传输,则取消下面两行的注释 #$ModLoad imudp #$UDPServerRun 514# Provide…...
python实现放烟花效果庆祝元旦
马上就要2025年元旦啦,提前祝大家新年快乐 完整代码下载地址:https://download.csdn.net/download/ture_mydream/89926458...
模型训练识别手写数字(二)
模型训练识别手写数字(一)使用手写数字图像进行模型测试 一、生成手写数字图像 1. 导入所需库 import cv2 import numpy as np import oscv2用于计算机视觉操作。 numpy用于处理数组和图像数据。 os用于文件和目录操作。 2. 初始化画布 canvas np.z…...
深入Vue2
frontend Vue2 学习内容参考 /在线运行 Element 学习内容参考 /视频教学 vue2 1. vue 实例 当一个 Vue 实例被创建时,它将 data 对象中的所有的 property 加入到 Vue 的响应式系统中 但是当使用Object.freeze(),会阻止修改现有的 property&#x…...
opencv-rust 系列3: Create_mask
前言: 这里只是opencv-rust自带示例的中文注解. 略微增加了一些代码也是我在调试时用到的. 调试方法可参见前文. 一. 这个程序还是有点难度的, 关键点在于: 创建了遮罩. 直接调用一个函数, 还是很简单的.窗口事件处理. 注册窗口回调函数, 用以处理鼠标事件进程同步和互斥锁. 为…...
Go语言初识
一、Go语言概述 Go语言是为了取代C和java的地位,既要保留C的简洁,也追求java的规模化开发 并行及分布式的支持,使得开发多核及多机器集群程序如同单机一样简单 Go语言从语言级别支持协程(goroutine, 轻量级线程),Go语言…...
Android Activity SingleTop启动模式使用场景
通知栏 当用户点击通知栏中的通知时,可以使用单顶启动模式来打开对应的活动,并确保只有一个实例存在。 简单集成极光推送 创建应用 获取appkey参数 切换到极光工作台 极光sdk集成 Project 根目录的主 gradle 配置 Module 的 gradle 配置 Jpush依赖配置 配置推送必须…...
PHP 代码执行相关函数
函数 说明 示例代码 ${} 用于复杂的变量解析,通常在字符串内用来解析变量或表达式。可以配合 eval 或其他动态执行代码的功能,用于间接执行代码。 eval(${flag}); eval() 用于执行一个字符串作为 PHP 代码。可以执行任何有效的 PHP 代码片段。没有…...
五周年,继续破浪前行
五周年,TapData 再一次带着自己的“乘风破浪”大队,在一个阳光明媚的日子里,把生日过在了海上。 头顶日升日落,这条属于全体 Tap-pers 的航船,再次校准航向,在船长的带领下,驶向下一个晴好的明…...
【操作系统】Linux之进程管理一
第1关:获取进程常见属性 ret.pidgetpid(); ret.ppidgetppid(); 第2关:进程创建操作-fork pid_t pid fork(); if(pid-1) printf("创建进程失败!"); else if(pid0) printf("Children"); else printf("Parent"); …...
C语言_数据在内存中的存储
1. 整数在内存中的存储 计算机中的整数有三种2进制表示方法 :原码、反码、补码。 三种表示方式均有符号位和数值位两个部分,最高一位的是符号位,剩下的都是数值位。符号位用“0”表示“正”,用“1”表示“负”。 正数的原、反、…...
华为原生鸿蒙操作系统:我国移动操作系统的新篇章
华为原生鸿蒙操作系统:我国移动操作系统的新篇章 引言 在移动操作系统领域,苹果iOS和安卓系统一直占据主导地位。然而,随着华为原生鸿蒙操作系统的正式发布,这一格局正在发生深刻变化。作为继苹果iOS和安卓系统后的全球第三大移动…...
队列的基本操作(数据结构)
1.实验内容: 编写一个程序sqqueue.cpp,实现环形队列(假设栈中元素类型ElemType 为 char)的各种基本运算,并在此基础上设计一个程序exp4_1.cpp,完成如下功能: 2.实验步骤: (1)初始化队列q (2)判断队列q是否非空 (3…...
linux开机自启动三种方式
方式一、 1:rc.local 文件 1、执行命令:编辑 “/etc/rc.local” vi /ect/rc.local 2、然后在文件最后一行添加要执行程序的全路径。 例如,每次开机时要执行一个 hello.sh,这个脚本放在 / usr 下面,那就可以在 “/et…...
AI创作者与人类创作者的协作模式
公主请阅 1. AI创作者的崛起1.1 AI创作者的工作原理1.2 AI创作者的优势 2. 人类创作者的独特价值2.1 创造性与情感2.2 伦理与价值观2.3 文化与背景 3. AI与人类的协作模式3.1 协同创作3.2 内容编辑3.3 数据驱动的创作3.4 跨媒体协作 4. AI与人类协作的挑战4.1 技术局限性4.2 版…...
Vim 调用外部命令学习笔记
Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...
深度学习在微纳光子学中的应用
深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向: 逆向设计 通过神经网络快速预测微纳结构的光学响应,替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
定时器任务——若依源码分析
分析util包下面的工具类schedule utils: ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类,封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz,先构建任务的 JobD…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
