2024.1.29 关于 Redis 缓存详解

news2024/11/16 18:05:50

目录

缓存基本概念

二八定律

Redis 作为缓存

缓存更新策略

定期生成

实时生成

内存淘汰策略

缓存使用的注意事项

关于缓存预热

关于缓存穿透

关于缓存雪崩

关于缓存击穿(瘫痪)


缓存基本概念

  • 所谓缓存,其实就是将一部分常用数据放到访问速度更快的地方,方便随时读取

实例理解

  • 硬件的访问速度一般为:CPU 寄存器 > 内存 > 硬盘 > 网络
  • 此时最常见的 便是使用 内存 作为 硬盘 的缓存,即 Redis 定位
  • 当然,硬盘 也能作为 网络 的缓存!因为硬盘的访问速度相对网络来说更快!
  • 比如 浏览器缓存
  • 浏览器通过 http/https 从服务器上获取数据(html、css、js、图片、视频、音频、字体 等)并进行展示
  • 像 图片、视频、音频等 这些体积大 又不太会改变的数据就可以保存到浏览器本地,即浏览器所在主机的硬盘上
  • 等到后续再打开该网页时,就不必重新从网络获取上述数据了!

二八定律

  • 指 20% 的数据,可以应对 80% 的请求

注意:

  • 缓存虽然速度快,但空间小
  • 大部分情况下,缓存仅存放一些热点数据即可,因为这些热点数据足以应对大多数场景

Redis 作为缓存

  • 我们通常使用 Redis 作为数据库(MySQL)的缓存

注意:

  • 数据库是十分重要的组件,即绝大部分商业项目均会涉及
  • 但 MySQL 的访问速度又相对较慢,因此我们便可使用 Redis 来作为 MySQL 的缓存

问题:

  • 为什么说关系型数据库性能不高?

回答:

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

注意:

  • 因为 MySQL 等数据库,效率相对较低,所以承担的并发量有限,一旦请求量多了,数据库的压力就会很大,甚至于很容易便宕机了
  • 服务器每处理一个请求,都需消耗一些硬件资源(CPU、内存、硬盘、网络 等)
  • 任意一种资源的消耗超出了机器所能提供的上限,此时机器便会很容易出现故障

问题:

  • 如何提高 MySQL 所能承担的并发量?(客观需求)

回答:

  1. 开源:引入更多的机器,构成数据库集群
  2. 节流:引入缓存,将一些频繁读取的热点数据,保存到缓存上,后续在查询数据时,如果缓存中已存在,便不再访问 MySQL,直接从缓存中拿数据即可(典型的方案)

缓存更新策略

  • 此处我们解决关于 如何知道 Redis 中应存储哪些数据,即哪些数据为 热点数据?

定期生成

  • 将访问数据,以日志形式给记录下来
  • 通过日志,将都使用到了哪些词给记录下来,此时便可以针对这些日志信息进行统计了
  • 统计这 一天/一周/一个月 每个词出现的频率,再根据频率降序排序
  • 再取出前 20% 的词,就可以认定这些词为 热点词
  • 接下来就可以将这些热点词 所涉及到的搜索结果给提前拎出来,并放到类似于 Redis 这样的缓存中了

注意点一:

  • 当然上述所讲的数据量是非常大的,所以我们可以写个程序来进行统计
  • 数据量可能大到说 一台机器都存不下
  • 此时便需要使用分布式的系统来存储这些日志(HDFS)
  • 再使用 hadoop 的 map-reduce 来写代码进行统计
  • 也可基于 HDFS 的 HBASE 这样的数据库来写 sql 统计
  • 这属于 大数据工程师 的日常工作

注意点二:

  • 此处的数据可以根据当前这里的统计纬度,来定期更新
  • 按照天级别统计的,就每天更新一次
  • 按照月级别统计的,就每个月更新一次
  • 写一套离线的流程(往往使用 shell,python 写脚本代码)
  • 然后通过 定时任务 的形式来触发

定时任务的内容包括:

  1. 完成统计热词的过程
  2. 根据热词,找到搜索结果的数据
  3. 将得到的缓存数据同步到缓存服务器上
  4. 控制这些缓存服务区自动重启

优点:

  • 上述过程,实际上实现起来还是比较简单的
  • 其过程更可控,缓存中的数据大多都比较固定,方便排查问题

缺点:

  • 实时性不够,如果出现一些突发性事件,有一些本来不是热词的内容成了热词
  • 此时新的热词就可能给后面的数据库啥的代码较大的压力
  • 比如 春节晚会 这个突发性热词

实时生成

  • 如果在 Redis 中查到了,就直接返回
  • 如果在 Redis 中查不到,就从数据库查,并将查到的结果同时写入 Redis  
  • 这样不停的写 Redis,就会使 Redis 的内存占用越来越多
  • 逐渐达到内存上限,此处的内存上限可通过配置 maxmemory 参数设定,即不一定指的是机器内存上限,Redis 中可通过配置设定最多使用多少内存
  • 达到内存上限后,再继续往 Redis 中插入数据的话,便会触发内存不够问题!
  • 而为了解决改问题,Redis 便引入了 内存淘汰策略
  • 通过内存淘汰策略,并经过一段时间的动态平衡,Redis 中的 key 将逐渐变为热点数据


内存淘汰策略

  • FIFO【先进先出】:将内存中存在时间最久的(也就是先来的数据)给淘汰掉
  • LRU【淘汰最久未使用的】:记录每个 key 的最近访问时间,将最近访问时间最老的 key 给淘汰掉
  • LFU【淘汰访问次数最少的】:记录每个 key 最近一段时间的访问次数,将访问次数最少的 key 给淘汰掉(相对靠谱
  • Random【随机淘汰】:从所有的 key 中抽取幸运儿被随机淘汰掉(不太合理)

注意:

  • 当然具体采取哪种策略,还需结合实际场景来具体问题具体分析
  • Redis 中有一个配置项,可以设置 Redis 采取上述哪种策略淘汰内存数据

缓存使用的注意事项

关于缓存预热

  • 当 Redis 服务器首次接入时,服务器中是没有数据的
  • 客户端先查询 Redis,如果没有查到,则再查 MySQL
  • 查到了之后,便会将数据给写入到 Redis 中
  • 针对上述情况,此时所有请求均会打给 MySQL
  • 并随着时间的推移,Redis 上的数据也越积越多
  • 自然 MySQL 所承担的压力也就越来越小了

解决方案:

  • 缓存预热 就是用来解决上述问题的
  • 此处我们可以将 定期生成 和 实时生成 给结合起来
  • 先通过离线的方式,根据统计,先找到一批热点数据,并将其导入到 Redis 中
  • 此时导入的这批热点数据,就能帮 MySQL 承担很大一部分压力了
  • 最后随着时间的推移,逐渐使用新的热点数据淘汰旧的热点数据

注意:

  • 定期生成 是不涉及预热的,仅实时生成涉及该问题

关于缓存穿透

  • 查询某个 key 时,Redis 和 MySQL 中均没有
  • 便可能导致 这次查询 ——> 没有,下次查询 ——> 仍然没有  的情况
  • 如果存在很多像这样的 key,并且还反复查询,一样也会给 MySQL 带来很大的压力

产生原因:

  1. 业务设计不合理,如缺少必要的参数校验环节,导致非法 key 也被运行查询(典型)
  2. 开发 或 运维误操作,不小心将部分数据从数据库上误删了(没那么典型,表现也是缓存穿透,误删操作,不一定能即时发现)
  3. 黑客恶意攻击(比较少见)

不靠谱的解决方案:

  • 通过改进业务 或 加强监控报警(亡羊补牢)
  • 事故出现之后,才采取行动!

靠谱的解决方案:(减低问题的严重性)

  1. 如果发现该 key 在 Redis  和 MySQL 上均不存在,此时直接将 key 写入 Redis 中,并将其 value 设成一个非法值(如 " ")
  2. 引入 布隆过滤器,将所有的 key 均插入到 布隆过滤器 中,每次查询 Redis 或 MySQL 前都先判定一下该 key 是否在存在于 布隆过滤器 上

具体解释:

  • 布隆过滤器,本质上结合了 哈希 与 位图 ,以比较小的空间开销,比较快的时间速度,实现针对 key 是否存在的判定

关于缓存雪崩

  • 短时间内,Redis 上大规模的 key 失效,导致缓存命中率陡然下降,进而导致 MySQL 的压力迅速上升,甚至直接宕机

产生原因:

  1. Redis 直接挂了(Redis 宕机 或 Redis 集群模式下大量节点宕机)
  2. Redis 虽正常运行,但可能由于之前短时间内设置了很多 key 给 Redis,且设置的过期时间均在同一时刻过期

注意:

  • 给 Redis 里设置 key 作为缓存时,有时候为了考虑缓存的时效性,便会设置过期时间(Redis 内存淘汰机制 配合着使用)

解决方案:

  1. 加强监控报警,加强 Redis 集群可用性的保证(集群监控、哨兵监控)
  2. 不给 key 设置过期时间 或 设置过期时间时通过添加随机因子来避免同一时刻过期

关于缓存击穿(瘫痪)

  • 相当于缓存雪崩的特殊情况
  • 此处是针对热点 key 突然过期,进而导致大量的请求直接访问到 MySQL 上,甚至直接引起数据库宕机

注意:

  • 热点 key 访问频率更高,影响更大

解决方案:

  1. 基于统计的方式筛选出热点 key ,并设置永不过期
  2. 进行必要的服务降级

理解服务降级:

  • 例如访问 MySQL 时,使用分布式锁,限制同时请求数据库的并发量
  • 例如本身服务器的功能有十个,但在特定情况下,可适当关闭一些不重要的功能,只保留核心功能(省电模式)

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

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

相关文章

向日葵企业“云策略”升级 支持Android 被控策略设置

此前,贝锐向日葵推出了适配PC企业客户端的云策略功能,这一功能支持管理平台统一修改设备设置,上万设备实时下发实时生效,很好的解决了当远程控制方案部署后,想要灵活调整配置需要逐台手工操作的痛点,大幅提…

计算机网络-数据交换方式(电路交换 报文交换 分组交换及其两种方式 )

文章目录 为什么要数据交换?总览电路交换电路交换的各个阶段建立连接数据传输释放连接 电路交换的特点电路交换的优缺点 报文交换报文交换流程报文交换的优缺点 分组交换分组交换流程分组交换的优缺点 数据交换方式的选择分组交换的两种方式数据报方式数据报方式的特…

正则表达式(RE)

什么是正则表达式 正则表达式,又称规则表达式(Regular Expression)。正则表达式通常被用来检索、替换那些符合某个规则的文本 正则表达式的作用 验证数据的有效性替换文本内容从字符串中提取子字符串 匹配单个字符 字符功能.匹配任意1个…

(一)Spring 核心之控制反转(IoC)—— 配置及使用

目录 一. 前言 二. IoC 基础 2.1. IoC 是什么 2.2. IoC 能做什么 2.3. IoC 和 DI 是什么关系 三. IoC 配置的三种方式 3.1. XML 配置 3.2. Java 配置 3.3. 注解配置 四. 依赖注入的三种方式 4.1. 属性注入(setter 注入) 4.2. 构造方法注入&a…

ES Serverless让日志检索更加便捷

前言 在项目中,或者开发过程中,出现bug或者其他线上问题,开发人员可以通过查看日志记录来定位问题。通过日志定位 bug 是一种常见的软件开发和运维技巧,只有观察日志才能追踪到具体代码。在软件开发过程中,开发人员会在代码中添加日志记录,以记录程序的运行情况和异常信…

【蓝桥杯日记】复盘篇二:分支结构

前言 本篇笔记主要进行复盘的内容是分支结构,通过学习分支结构从而更好巩固之前所学的内容。 目录 前言 目录 🍊1.数的性质 分析: 知识点: 🍅2.闰年判断 说明/提示 分析: 知识点: &am…

【Linux操作系统】:Linux开发工具编辑器vim

目录 Linux 软件包管理器 yum 什么是软件包 注意事项 查看软件包 如何安装软件 如何卸载软件 Linux 开发工具 Linux编辑器-vim使用 vim的基本概念 vim的基本操作 vim正常模式命令集 插入模式 插入模式切换为命令模式 移动光标 删除文字 复制 替换 撤销 跳至指…

C++——list的使用及其模拟实现

list 文章目录 list1. 基本使用1.1 list对象的定义1.2 增(插入数据)1.3 删(删除数据)1.4 遍历访问 2. 模拟实现2.1 节点类ListNode2.2 封装ListNode类,实现list基本功能2.3 实现迭代器iterator2.3.1 实现const迭代器co…

使用Hutool工具包解析、生成XML文件

说明&#xff1a;当我们在工作中需要将数据转为XML文件、或者读取解析XML文件时&#xff0c;使用Hutool工具包中的XMLUtil相关方法是最容易上手的方法&#xff0c;本文介绍如何使用Hutool工具包来解析、生成XML文件。 开始之前&#xff0c;需要导入Hutool工具包的依赖 <de…

力扣hot100 柱状图中最大的矩形 单调栈

Problem: 84. 柱状图中最大的矩形 文章目录 思路复杂度Code 思路 &#x1f468;‍&#x1f3eb; 参考地址 复杂度 时间复杂度: O ( n ) O(n) O(n) 空间复杂度: O ( n ) O(n) O(n) Code class Solution {public static int largestRectangleArea(int[] height){Stack&l…

疯狂的方块

欢迎来到程序小院 疯狂的方块 玩法&#xff1a;两个以上相同颜色的方块连在一起&#xff0c;点击即可消除&#xff0c;不要让方块到达顶部&#xff0c;消除底部方块哦^^。开始游戏https://www.ormcc.com/play/gameStart/263 html <div id"gameDiv"> <canv…

fiber学习

React原理&#xff1a;通俗易懂的 Fiber - 掘金

nacos启动失败解决

报错信息 Caused by: com.mysql.cj.jdbc.exceptions.PacketTooBigException: Packet for query is too large (2,937 > 2,048). You can change this value on the server by setting the ‘max_allowed_packet’ variable. 情景复现 最近使用mac正在运行一个nacos的spri…

treeview

QML自定义一个TreeView&#xff0c;使用ListView递归 在 Qt5 的 QtQuick.Controls 2.x 中还没有 TreeView 这个控件&#xff08;在 Qt6 中出了一个继承自 TableView 的 TreeView&#xff09;&#xff0c;而且 QtQuick.Controls 1.x 中的也需要配合 C model 来自定义&#xff0c…

Win10 双网卡实现同时上内外网

因为需要同时上内网和外网&#xff0c;但公司做了网络隔离&#xff0c;不能同时上内外网&#xff0c;所以多加了块无线网卡&#xff0c;配置双网关实现同时上内外网&#xff0c;互不影响 打开 Windows PowerShell&#xff08;管理员&#xff09;&#xff0c;输入&#xff1a;ro…

Github 2024-01-30 开源项目日报 Top10

根据Github Trendings的统计&#xff0c;今日(2024-01-30统计)共有10个项目上榜。根据开发语言中项目的数量&#xff0c;汇总情况如下&#xff1a; 开发语言项目数量Python项目4TypeScript项目2Jupyter Notebook项目2HTML项目1Rust项目1C项目1 稳定扩散Web UI 创建周期&…

C++核心编程:类和对象 笔记

4.类和对象 C面向对象的三大特性为:封装,继承,多态C认为万事万物都皆为对象&#xff0c;对象上有其属性和行为 例如&#xff1a; 人可以作为对象&#xff0c;属性有姓名、年龄、身高、体重...,行为有走、跑、跳、说话...车可以作为对象&#xff0c;属性有轮胎、方向盘、车灯…

万兆网络数据传输-scp加速

在万兆甚至更高的网络带宽场景下 scp 的传输效率并不如人意。毕竟 scp 是旧时代的产物&#xff0c;那时千兆网络都很罕见。以下通过修改压缩方式的方法提升数据的传输速度。同时也采用 nc &#xff0c; bbcp 和 rsync 进行了对比测试。 目录 scp采用默认方式更改压缩算法为 aes…

seata 分布式

一、下载安装seata 已经下载好的朋友可以跳过这个步骤。这里下载的是seata1.6.1这个版本。 1、进入seata官网 地址&#xff1a; https://seata.io/zh-cn/index.html 2、进入下载 3、点击下载地址 下载地址&#xff1a; https://github.com/seata/seata 二、配置seata 进入c…

vue3项目中让echarts适应div的大小变化,跟随div的大小改变图表大小

目录如下 我的项目环境如下利用element-resize-detector插件监听元素大小变化element-resize-detector插件的用法完整代码如下&#xff1a;结果如下 在做项目的时候&#xff0c;经常会使用到echarts&#xff0c;特别是在做一些大屏项目的时候。有时候我们是需要根据div的大小改…