当前位置: 首页 > news >正文

Redis——缓存

什么是缓存?

缓存是计算机中一个经典的概念,其实本质就是将常用的数据放到访问速度快的地方,方便读取。

对于硬件的访问速度来说,通常情况如下:
CPU寄存器 > 内存 > 硬盘 > 网路
但是对于计算机硬件来说,往往访问速度快的设备,成本就会越高,存储空间就会越小。缓存是快,但是空间是不足的,所以,缓存大部分就是放一些热点数据

在一个网站中,通常使用像MySQL这样的关系型数据库来存储数据。关系型数据库虽然功能强大,但是有一个缺陷就是性能不高(这里是相对于redis来说)

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

  • 数据库将数据存储到硬盘上,硬盘上的IO速度并不快,尤其是随机访问
  • 如果查询不能命中索引,就需要进行表的遍历,这会大大增加硬盘IO次数
  • 如果涉及到了一些复杂的查询,需要用到笛卡尔积,效率就会下降很多

而且,在面对并发量大的情况下,数据库可能会宕机

为什么并发量大的情况下会宕机?

  • 服务器每次处理一个请求,都是需要消耗一定的硬件资源的(CPU、内存、硬盘、网络带宽)
  • 一个服务器的资源是有限的,一个请求消耗一份资源,请求多了,后续的请求就没有资源可用了,无法得到处理,就有可能会宕机

如何让数据库承担更大的并发量呢?

  • 开源:引入更多的机器,部署更多的数据库实例,构成集群。比如:分库分表、主从复制等
  • 节流:引入缓存,使用其他的方式保存经常访问的数据,从而降低数据库的压力

其中Redis就是缓存的一个经典案列,Redis的访问速度比MySQL快,或者说处理同一个访问请求,Redis消耗的系统资源比MySQL少很多,因此Redis能支持的并发量大

  • Redis数据在内存中,访问速度比硬盘快
  • Redis只支持key-value的形式,不涉及复杂查询的限制规则

在这里插入图片描述

  • 客户端访问服务器的时候,发起查询请求
  • 业务服务器先查询Redis,看数据是否在Redis存在,如果存在直接返回,如果不存在就访问MySQL

那么问题来了如何知道Redis应该存储哪些数据呢?

定期生成

每隔一定的周期,对于访问的数据频次做统计,挑选出访问最高的前N%的数据,这些数据就是热点数据。

比如:用户来搜索引擎中输入一个关键字,有些关键字就是高频出现的,搜索引擎的服务器中可以通过日志的方式记录下来,然后每隔一定的时间将结果统计出来,就可以得到热点数据了。

但是想过没有,如果面对像一个节假日的突发情况,某个词会出现的很频繁,但是过了这段时间,就不会有人搜索这个词。 这种情况下,如果采取了定期生成的方式,是不是就不合适了呢??

所以基于上面的场景,有了实时生成的策略

实时生成

先给缓存设定容量上限(可以通过Redis中的maxmemory参数来设定)
接下来用户的每次查询:

  • 如果Redis存在,就直接返回
  • 如果Redis不存在,就从数据库中查询,将查询到的结果写入到Redis中

但是,如果缓存达到了上限,就会发出淘汰机制,将一些“相对不热门的”的数据淘汰掉。

通常的淘汰策略有如下几种

  • FIFO(First In First Out)先入先出:将缓存时间最久的数据淘汰掉
  • LRU(Least Recently Used)淘汰最久没使用的:记录每个key的最近访问时间,将最近的访问时间最老的key淘汰掉
  • LFU(Least Frequently Used)淘汰访问次数最少的:记录每个key最近一段时间的访问次数,将访问次数最少的key淘汰掉
  • Random随机淘汰:从所有的key中随机淘汰一个key

淘汰策略,用户可以自己实现,当然Redis也提供了内置的淘汰策略,以便直接使用。

Redis的内置淘汰策略如下:

  • volatile-lru: 当内存不足以容纳新写入的数据时,从设置了过期时间的key中使用LRU算法进行淘汰
  • allkeys-lru:当内存不足以容纳新写入的数据时,从所有的key中使用LRU算法进行淘汰
  • volatile-lfu:当内存不足以容纳新写入的数据时,在过期的key中,使用lfu算法进行淘汰
  • allkeys-lru:当内存不足以容纳新写入的数据时,从所有的key中使用lfu算法进行淘汰
  • volatile-random:当内存不足以容纳新写入的数据时,从所有的key中随机淘汰一个key
  • volatile-ttl:在设置了过期时间的key中,根据过期时间来淘汰。 (越早的过期key,越早被淘汰)
  • noeviction:这是Redis采用的默认策略,当内存不足的时候,写入操作会报错

缓存预热

什么是缓存预热

  • 使用Redis作为MySQL的缓存,当MySQL刚刚启动的时候,或者Redis大批量的key失效以后,由于Redis自身没啥数据,会直接访问到MySQL中,就会对MySQL造成巨大的压力。

所以要将热点数据准备好,直接写入到Redis中。

缓存穿透(Cache penetration)

什么是缓存穿透

  • 当一个key在Redis中不存在,并且也不在MySQL中,那么如果这时候并发量很大,就会造成巨大的压力。 这就叫做缓存穿透

为何产生:

  • 业务设计的不合理,比如缺少必要的参数校验,导致非法的key进行查询
  • 开发/运维误操作:将部分的key删除掉了

如何解决

  • 针对要查询的参数进行严格的校验,比如查询的key是用户的手机号,那么就需要校验当前的key是否满足一个合法的手机号的格式
  • 针对数据库也不存在的key,也存储到Redis中,比如value就随便设置为一个“”,避免后续频繁的访问数据库
  • 在应用程序中使用布隆过滤器,先进行一次判断,降低Redis的压力

缓存雪崩

什么是缓存雪崩

  • 短时间内大量的key在缓存上失效,导致数据库压力剧增,甚至是宕机了

为何产生:

大规模的key失效有两种情况

  • Redis挂了
  • Redis设置了大量的key同时过期了

如何解决?

  • 部署高可用的Redis集群,采用完善的监控报警系统
  • 不给key设置过期时间 或者 设置过期时间的时候随机添加随机时间因子

缓存击穿(Cache breakdown)

什么是缓存击穿

  • 相当于缓存雪崩的特殊场景,针对热点的key,突然过期了,导致大量的请求打到了数据库上,引发了宕机

如何解决?

  • 基于统计的方式发现热点key,并设置永不过期
  • 进行服务降级,例如采用分布式锁,限制同时请求数据库的并发量。 或者进行分流操作,将流量分到其他的服务器中

相关文章:

  • 15年408-数据结构
  • Stable Diffusion绘画 | SDXL模型的优缺点及模型推荐
  • 【linux进程】进程状态僵尸进程孤儿进程
  • 遥感影像-语义分割数据集:山体滑坡数据集详细介绍及训练样本处理流程
  • 计算机毕业设计 基于Hadoop的智慧校园数据共享平台的设计与实现 Python 数据分析 可视化大屏 附源码 文档
  • 防火墙详解(二)通过网页登录配置华为eNSP中USG6000V1防火墙
  • Git 使用方法
  • 揭秘 Elasticsearch 集群架构,解锁大数据处理神器
  • SSE协议
  • 【架构】前台、中台、后台
  • Jmeter关联,断言,参数化
  • 如何使用ssm实现基于JavaWeb的个人健康信息管理系统
  • 嵌入式单片机底层原理详解
  • 力扣30. 串联所有单词的子串
  • 【Linux】部署 flask
  • 「前端早读君006」移动开发必备:那些玩转H5的小技巧
  • C++类的相互关联
  • co模块的前端实现
  • docker容器内的网络抓包
  • Javascript编码规范
  • Node + FFmpeg 实现Canvas动画导出视频
  • Object.assign方法不能实现深复制
  • React组件设计模式(一)
  • scrapy学习之路4(itemloder的使用)
  • 阿里云前端周刊 - 第 26 期
  • 彻底搞懂浏览器Event-loop
  • 警报:线上事故之CountDownLatch的威力
  • 聊聊directory traversal attack
  • 全栈开发——Linux
  • 如何合理的规划jvm性能调优
  • 世界编程语言排行榜2008年06月(ActionScript 挺进20强)
  • 通过几道题目学习二叉搜索树
  • 无服务器化是企业 IT 架构的未来吗?
  • 用element的upload组件实现多图片上传和压缩
  • MiKTeX could not find the script engine ‘perl.exe‘ which is required to execute ‘latexmk‘.
  • Prometheus VS InfluxDB
  • 大数据全解:定义、价值及挑战
  • # linux 中使用 visudo 命令,怎么保存退出?
  • #565. 查找之大编号
  • #Linux(make工具和makefile文件以及makefile语法)
  • #LLM入门|Prompt#2.3_对查询任务进行分类|意图分析_Classification
  • #systemverilog# 之 event region 和 timeslot 仿真调度(十)高层次视角看仿真调度事件的发生
  • (04)odoo视图操作
  • (09)Hive——CTE 公共表达式
  • (1)STL算法之遍历容器
  • (27)4.8 习题课
  • (C语言)求出1,2,5三个数不同个数组合为100的组合个数
  • (k8s)Kubernetes 从0到1容器编排之旅
  • (安卓)跳转应用市场APP详情页的方式
  • (补充):java各种进制、原码、反码、补码和文本、图像、音频在计算机中的存储方式
  • (附源码)spring boot球鞋文化交流论坛 毕业设计 141436
  • (过滤器)Filter和(监听器)listener
  • (四)docker:为mysql和java jar运行环境创建同一网络,容器互联
  • (算法设计与分析)第一章算法概述-习题
  • (转)C#调用WebService 基础