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 为例):

  1. MySql 把数据存储在硬盘上,硬盘上的 IO 速度并不快,尤其是在随机访问时;
  2. 使用 MySql 进行查询过程中,如果查询不能命中索引,就需要进行表的遍历,这会大大的增加硬盘 IO 的次数;
  3. MySql 对于 SQL 在执行会做一系列的解析、校验、优化的工作;
  4. 如果使用 MySql 做一些复杂查询,比如:多表联合查询,需要使用笛卡尔积进行操作,效率会降低很多。

        因为 MySql 等数据库有着上面的问题,所以承担的并发量就有限,一旦请求的数量多了,数据库的压力就会很大,就可能会宕机,那么如何提高 MySql 能承担的并发量呢?有以下两种方案可以做到:

  1. 开源:引入更多的机器,构成数据库集群;
  2. 节流:引入缓存,把一些频繁读取的热点数据保存到缓存中,这样后续在查询数据的时候,先在缓存中查询,如果缓存中已经存在就不再访问 MySql 了。

         Redis 就是作为数据库缓存的常见方案,关于 Redis 可以作为 Mysql 缓存有以下两种原因:

  • Redis 数据在内存中,访问内存速度比访问硬盘快很多;
  • Redis 只是支持简单的 key-value 存储,不涉及复杂的查询的诸多限制规则。

        此时当 Redis 作为 MySql 的缓存后,他们的关系,可以形象的如下图所示:

        Redis 就像盾牌一样会先接收大部分的请求,少部分 Redis 上没有的数据才会请求 MySql。

注意:只有在进行读操作时,使用 Redis 作为缓存才有作用,如果进行的是写操作,那还是要对 MySql进行操作的

三、缓存的更新策略

        通过上面的介绍,我们知道引入缓存的意义是用来存一些热点数据,并配合二八定律可以很好的分担 Mysql 的压力,可是什么数据是“热点数据”呢?对于存储的热点数据就有以下两种生成方式,下面来展开介绍一下这两种方式。

1.定期生成

        定期生成这种策略,就是每隔一定的周期(比如一天/一周/一个月),对访问数据的频次进行统计,挑选出访问频次最高的前 N%来存储在缓存中。

        使用这种策略的优缺点如下:

  • 优点:定期生成的策略实现起来比较简单,过程可控,方便排查问题;
  • 缺点:实时性不够,如果出现一些突发事件,有一些本来不是热词的内容突然成为了热词,新的热词就可能就数据库带来较大的压力。

        关于上述缺点中的实时性有一个很好的例子,那就是在过年时搜索“春节晚会”的时候,这个词一般只会在过年期间会被人们进行搜索,并且搜索量巨大,此时由于定期生成周期还没有进行更新,就会造成这些搜索请求直接访问后面的数据库了。 

2.实时生成

        为了弥补上述定期生成策略的缺点,实时生成会采用动态生成热点数据的方式,我们首先需要给缓存设定容量上限(在 Redis 配置文件中的 maxmemory 参数可以设定容量上限),接下来用户的每次查询操作就会经历以下的步骤:

  1. 如果在 Redis 中查找到,就直接返回;
  2. 如果 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 带来很大的压力。出现这种问题的原因有以下几条:

  1. 代码设计不合理,比如缺少必要的参数校验环节,导致非法的 key 也被进行查询了;
  2. 在开发过程中,不小心把部分数据从数据库中误删了;
  3. 遭到黑客的恶意攻击。

        那么如何解决缓存穿透这样的问题呢?有以下几个解决方案:

  • 针对要查询的参数进行严格的合法性校验;
  • 针对 Redis 和 Mysql 中都不存在的 key 仍写入到 Redis 中,将这里的 value 也设成一个非法值(比如“”);
  • 引入 布隆过滤器,在每次查询 Redis/MySql 之前都先判定一下 key 是否在 布隆过滤器 上存在(把所有 key 都插入到 布隆过滤器 中)。

        上述解决方法中的 布隆过滤器 是一种本质上结合了 hash 与 bitmap 的数据结构,它可以以比较小的空间开销,比较快的时间速度来实现针对 key 是否存在做出判定。 

3.缓存雪崩(Cache avalanche)

        缓存雪崩就是指在短时间内,Redis 上大规模的 key 失效,导致缓存命中率陡然下降,并且 MySql 的压力迅速上升,导致 MySql 直接宕机。出现这个问题的原因有主要两种:

  1. Redis 服务器宕机 / Redis 集群模式下大量的节点宕机;
  2. Redis 没有问题,但是由于之前短时间内设置的很多 key 它们的过期时间是相同的。

        那么如何解决这种问题呢? 有以下几种解决方案:

  • 增加并完善报警体系,争取在第一时间发现 Redis 服务器宕机;
  • 部署高可用的 Redis 集群;
  • 不给 key 设置过期时间 / 设置过期时间的时候添加随机的因子(避免同一时刻过期)。

4.缓存击穿(Cache breakdown)

        缓存击穿可以看作缓存雪崩的特殊情况,是指热点 key 突然过期了,导致大量的请求直接访问到 MySql 中,使 MySql 服务器压力骤增甚至宕机。

        解决这种问题的方式有以下几种:

  • 基于统计的方式发现热点 key 并且设置永不过期;
  • 进行必要的服务降级,例如访问 Mysql 的时候使用分布式锁,限制同时请求 MySql 的并发数。

·结尾

        文章到此就要结束了,关于 Redis 作为缓存的意义,更新缓存中实时生成时需要用到的淘汰策略,以及在使用 Redis 作为缓存时需要注意的一些事项介绍的也差不多了,本篇文章以文字为主,希望大家可以很好的理解其中的内容,如果本篇文章对你有所帮助还是希望能得到你的三连支持咯~~如果对文章内容有什么问题,欢迎在评论区进行留言讨论,我们下一篇文章再见~~~

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

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

相关文章

机器学习在智能水泥基复合材料中的应用与实践

在人工智能与复合材料技术融合的背景下,复合材料的研究和应用正迅速发展,创新解决方案层出不穷。从复合材料性能的精确预测到复杂材料结构的智能设计,从数据驱动的材料结构优化到多尺度分析,人工智能技术正以其强大的数据处理能力…

Linux 权限的理解

内容摘要 本文内容包括shell的运行原理,包括外壳程序的原理、理解、和意义,以及从两个方面对于权限的理解(人和事物的属性)、修改文件的权限,包括修改文件的拥有者、修改文件拥有者所在的组的用户以及修改文件的三类用…

【linux】线程(二)

10. pthread_t 类型 注意: 每一个线程的库级别的tcb的起始地址,就是线程的 tid每一个线程都有自己独立的栈结构线程和线程之间,也是可以被其他线程看到并访问的(比如全局函数) 代码 如果想要进程拥有私人的全局变量(即…

关于武汉芯景科技有限公司的限流开关芯片XJ6288开发指南(兼容SY6288)

一、芯片引脚介绍 1.芯片引脚 二、系统结构图 三、功能描述 1.EN引脚控制IN和OUT引脚的通断 2.OCB引脚指示状态 3.过流自动断开

C++ [项目] 恶魔轮盘赌

现在才发现C游戏的支持率这么高,那就发几篇吧 零、前情提要 此篇是我与 同学的共创,他负责写人,我负责写机,简称人机, 不过有一点小插曲…… 一、基本介绍 支持Dev-C5.11版本(务必调为英文输入法),基本操作看游戏里的介绍,怎么做的……懒得说,能看懂就看注释,没有…

Vue3结合vue-plugin-hiprint实现自定义打印模板设计与布局

简介 在现代Web应用开发中,打印功能是不可或缺的一部分,尤其是在需要输出标准化文档的场景下。本文将详细介绍如何在Vue3项目中利用vue-plugin-hiprint插件实现一个可定制的打印模板设计器,并通过具体示例来展示其配置与使用方法。 技术栈 …

Python如何导入模块及常见的导入方法

😀前言 在 Python 编程中,模块(Module)是非常重要的工具。它们可以帮助我们将代码进行逻辑分割和复用,从而提高代码的可读性和可维护性。本文将详细介绍如何导入模块、使用常见的导入方法,并简要介绍一些常…

[分享] SQL在线编辑工具(好用)

在线SQL编写工具(无广告) - 在线SQL编写工具 - Web SQL - SQL在线编辑格式化 - WGCLOUD

若依微服务15 - RuoYi-Vue3 实现前端独立运行

正文开始: RuoYi-Vue3 使用 Vue3 Element Plus Vite 技术栈。 GitHub 开源地址:https://github.com/yangzongzhuan/RuoYi-Vue3 本文介绍使用若依提供的在线后端接口,仅启动前端项目并进行界面开发,而无需启动后端服务。 一、克隆…

Vue笔记-浏览器窗口改变时,重新计算表格高度并设置

当窗口大小改变时,你监听 window 对象的 resize 事件,然后在事件处理程序中重新计算表格的高度。在 Vue 中,可以在组件中通过 created 生命周期钩子来添加事件监听器,然后在组件销毁时移除事件监听器。 如下vue代码: …

33 类与对象 · 下

目录 一、构造函数的深入 (一)构造函数的其他特点 (二)使用例 1、Date类与Time类显示写 2、Date类与Time类写一部分 (三)总结 (四)初始化顺序小题目 二、类型转化 &#xff…

Linux Redis查询key与移除日常操作

维护老项目Express node 编写的后端程序、有这么一个方法、没有设置redis过期时间(建议设置过期时间,毕竟登录生产服务器并不是每个人都有权限登录的!!!)。如果变动只能通过登录生产服务器、手动修改… 于…

@Autowired和@Resource的用法与区别

前言: Autowired 和 Resource 来自不同的“父类”,其中 Autowired 是 Spring 定义的注解,而 Resource 是 Java 定义的注解,它来自于 JSR-250(Java 250 规范提案)。当它们的实现类只有一个时,那…

github pages + hugo 搭建静态博客网站

体验地址 1. 起因, 目的: 其实6年前,我就写过这个。 项目代码 博客地址 最近想改写一下。 github 推荐的主题是 Jekyll, 我当时用的就是这个,感觉很麻烦。尤其是文章命名。 新的主题 hugo 用起来还行。 2.过程: 过程记录&am…

代码随想录算法训练营第六天|454四数相加II、 383赎金信、15三数之和、18四数之和

day06 1. 454四数相加II 首先定义 一个unordered_map,key放a和b两数之和,value 放a和b两数之和出现的次数。遍历大A和大B数组,统计两个数组元素之和,和出现的次数,放到map中。定义int变量count,用来统计 …

新电脑Win11家庭中文版跳过联网激活方法(教程)

预装Win11家庭中文版的新电脑,如何跳过联网激活;由于微软限制必须要联网激活,需要使用已有的微软账户登入或者注册新的微软账户后才可以继续开机使用,Win11联网后系统会自动激活。下面介绍一下初次开机初始化电脑时如何跳过联网激…

虚拟滚动列表如何实现?

highlight: a11y-dark 虚拟滚动列表&#xff0c;虚拟滚动的关键在于只渲染当前视口内可见的数据项&#xff0c;而不是一次性渲染所有数据项。这可以显著提高性能&#xff0c;尤其是在处理大量数据时。 以下是一个完整的虚拟滚动列表的示例代码&#xff1a; <!DOCTYPE htm…

RFC2616 超文本传输协议 HTTP/1.1

一、URL-俗称“网址” HTTP 使用 URL(Uniform Resource Locator&#xff0c;统一资源定位符)来定位资源&#xff0c;它是 URI(Uniform Resource Identifier&#xff0c;统一资源标识符)的子集&#xff0c;URL 在 URI 的基础上增加了定位能力 URI 除了包含 URL&#xff0c;还包…

ADC的交流参数

ADC的交流参数是衡量其在处理交流信号时性能的关键指标。一般包括&#xff1a; 1 信噪比&#xff08;Signal-to-Noise Ratio, SNR&#xff09; 这是衡量ADC输出信号中有用信号与噪声水平的比值。信噪比越高&#xff0c;表示ADC的性能越好。 SNR (dB) MaxRMSSignal / RMSNoise…

【你也能从零基础学会网站开发】 SQL Server结构化查询语言数据操作应用--DML篇 select语句数据查询操作详解 今天干货满满!《1024特别篇》

&#x1f680; 个人主页 极客小俊 ✍&#x1f3fb; 作者简介&#xff1a;程序猿、设计师、技术分享 &#x1f40b; 希望大家多多支持, 我们一起学习和进步&#xff01; &#x1f3c5; 欢迎评论 ❤️点赞&#x1f4ac;评论 &#x1f4c2;收藏 &#x1f4c2;加关注 select查询语句…