Redis缓存

概念 

核⼼思路就是把⼀些常⽤的数据放到触⼿可及(访问速度更快)的地⽅,⽅便随时读取.

速度快的设备,可以作为速度慢的设备的缓存

(CPU寄存器>内存>硬盘>网络)

最常见的是,使用内存作为硬盘的缓存

硬盘也可以作为网络的缓存,浏览器的缓存

浏览器通过http/https从服务器上获取到数据(html,css,js,图片,视频...),像图片这样体积大,又不太改变的数据,就可以保存到浏览器本地(浏览器所在主机的硬盘上),后续再打开这个页面,就不必重新从网络上获取上述数据了

缓存的意义:二八定律

缓存速度虽然快,但是空间小,20%的数据,可以应对80%的请求

使用Redis作为缓存

通常使用redis作为数据库的缓存

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

1. 数据库把数据存储在硬盘上,硬盘的IO速度并不快.尤其是随机访问.

2. 如果查询不能命中索引,就需要进⾏表的遍历,这就会⼤⼤增加硬盘IO次数.

3. 关系型数据库对于SQL的执⾏会做⼀系列的解析,校验,优化⼯作.

4. 如果是⼀些复杂查询,⽐如联合查询,需要进⾏笛卡尔积操作,效率更是降低很多.

因为mysql等数据库,效率比较低,所以承担的并发量就有限.一旦请求数量多了,数据库的压力就会很大,甚至很容易宕机了

服务器每次处理一个请求,一定要消耗一些硬件资源(cpu,内存,硬盘...),任意一种资源的消耗超出了机器能提供的上限,机器就很容器出现故障了

如何提高mysql能承担的并发量?

  • 开源:引入更多的机器,构成数据库集群
  • 节流:引入缓存,使用其它的方式保存经常访问的热点数据,从而降低直接访问数据库的请求数量,Redis 就是⼀个⽤来作为数据库缓存的常⻅⽅案

虽然redis只能存少数数据,但是大部分请求都是使用的这少数的热点数据

Redis能⽀持的并发量更⼤:

  • Redis数据在内存中,访问内存⽐硬盘快很多.
  • Redis只是⽀持简单的key-value存储,不涉及复杂查询的那么多限制规则.

注意:

缓存是⽤来加快"读操作"的速度的.如果是"写操作",还是要⽼⽼实实写数据库,缓存并不能 提⾼性能. 

缓存的更新策略

如何知道redis中应该存储哪些数据?

如何知道哪些数据是热点数据呢?

1.定期生成

每隔⼀定的周期(⽐如⼀天/⼀周/⼀个⽉),对于访问的数据频次进⾏统计.挑选出访问频次最⾼的前N%的数据. 

会把访问的数据,给以日志的形式记录下来

然后对日志进行统计,统计某段时间,每个词出现的频率,再根据频率降序排序,取出前N%的词,就可以把这些词认为是"热点词"

数据量可以很大,一台机器存不下,就需要使用分布式系统来存储这些日志(HDFS),再使用hadoop的map-reduce来写代码,进行统计,也可以使用基于HDFS的HBASE这样的数据库来写sql统计

把这些热点词,涉及到的结果,,提前拎出来,放到类似于redis这样的缓存中

此处的数据,就可以根据当前这里统计的维度,来定期更新


写一套离线的流程(往往使用shell,python写脚本代码),可以通过定时任务来触发

  • a)完成统计热词的过程
  • b)根据热词,找到搜索结果的数据
  • c)把得到缓存数据同步到缓存服务器上
  • d)控制这些缓存服务器自动重启

优点:

实现比较简单,过程可控(缓存中的有什么内容比较固定),方便排查问题

缺点:

实时性不够,如果出现一些突发性事件,有一些本来不是热词的内容,成了热词,新的热词就可能给后面的数据库带来较大的压力

2.实时生成

先给缓存设定容量上限(可以通过Redis配置⽂件的 maxmemory 参数设定):

  • 如果在redis查到了,就直接返回
  • 如果redis不存在,就从数据库查,把查到的结果同时也写入redis

这样不停的写redis,就会使redis的内存占用越来越多,逐渐达到内存上限

此时继续往里面插入数据,就会触发问题,为了解决上述情况,redis就引入了"内存淘汰策略"

[经典面试题]内存淘汰策略

FIFO (First In First Out) 先进先出

把缓存中存在时间最久的(也就是先来的数据)淘汰掉.

LRU(LeastRecentlyUsed)淘汰最久未使⽤的

记录每个key的最近访问时间.把最近访问时间最⽼的key淘汰掉.

LFU(LeastFrequently Used)淘汰访问次数最少的

记录每个key最近⼀段时间的访问次数.把访问次数最少的淘汰掉.

Random随机淘汰

从所有的key中抽取幸运⼉被随机淘汰掉.

以甄嬛传为例

后宫佳丽三千,相当于数据库中的全量数据.经常宠幸的妃⼦相当于热点数据,是放在缓存中的.

今年选秀的⼀批新的⼩主,其中有⼀个被你看上了.宠信新⼈,⾃然就需要有旧⼈被冷落.到底谁是要被冷落的⼈呢?

• FIFO:皇后是最先受宠的.现在已经年⽼⾊衰了.皇后失宠.

• LRU:统计最近宠幸时间.皇后(⼀周前),熹妃(昨天),安答应(两周前),华妃(⼀个⽉前).华妃失宠. • LFU:统计最近⼀个⽉的宠幸次数,皇后(3次),熹妃(15次),安答应(1次),华妃(10次).安答应失宠.

• Random:随机挑⼀个妃⼦失宠.

具体采用哪种策略,结合实际场景 

Redis内置的淘汰策略如下:

策略含义
volatile-lru当内存不⾜以容纳新写⼊数据时,从设置了过期时间的key中使⽤LRU(最近最少使⽤)算法进⾏淘汰(设置了过期时间的就算,包括过期时间还没到的)
allkeys-lru当内存不⾜以容纳新写⼊数据时,从所有key中使⽤LRU(最近最少使⽤)算法进 ⾏淘汰.
volatile-lfu当内存不⾜以容纳新写⼊数据时,在过期的key中,使⽤LFU算法 进⾏删除key
allkeys-lfu内存不⾜以容纳新写⼊数据时,从所有key中使⽤LFU算法进⾏ 淘汰
volatile-random当内存不⾜以容纳新写⼊数据时,从设置了过期时间的key中,随机淘汰数 据. 
allkeys-random当内存不⾜以容纳新写⼊数据时,从所有key中随机淘汰数据.
volatile-ttl在设置了过期时间的key中,根据过期时间进⾏淘汰,越早过期的优先被淘汰. (相当于FIFO,只不过是局限于过期的key)
noeviction默认策略,当内存不⾜以容纳新写⼊数据时,新写⼊操作会报错,不适合实时更新缓存

经过一段时间的"动态平衡",redis中的key就逐渐都成了热点数据了

缓存使用的注意事项[重点]

缓存预热(Cachepreheating)

缓存中的数据

1.定期生成(不涉及预热)

2.实时生成

redis服务器首次接入之后,服务器里是没有数据的,此时所有的请求都会给mysql,随着时间的推移,redis上的数据越来越多,mysql承担的压力就小了

缓存预热,就是用来解决上述问题的

处理:

把定期生成和实时生成结合一下

先通过离线的方式,通过一些统计的途径,把热点数据找到一批,导入到redis后,此时导入的这批热点数据,就能帮mysql承担很大的压力了

随着时间的推移,逐渐就使用新的热点数据淘汰旧的数据

缓存穿透(Cachepenetration)

查询某个key,在redis中没有,mysql也没有,这个key肯定也不会被更新到redis中

如果像这样的数据,存在很多,并且还反复查询,一样也会给mysql带来压力

为什么会出现这样的情况:

  • 业务设计不合理.⽐如缺少必要的参数校验环节,导致⾮法的key也被进⾏查询了.
  • 开发/运维误操作.不⼩⼼把部分数据从数据库上误删了.
  • ⿊客恶意攻击.

处理:

通过改进业务/加强监控报警=>亡羊补牢

更靠谱的方案:

1)针对要查询的参数进⾏严格的合法性校验.⽐如要查询的key是⽤⼾的⼿机号,那么就需要校验当前 key 是否满⾜⼀个合法的⼿机号的格式

2)如果发现这个key,在redis和mysql上都不存在,仍然写入redis中,value设置成一个非法值(比如" "),避免后续频繁访问数据库.

3)还可以引入布隆过滤器,每次查询redis/mysql之前,都先判定一下key是否在布隆过滤器上存在(把所有的key都插入到布隆过滤器),再真正查询

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

缓存雪崩(Cacheavalanche)

在短时间内,redis上大规模的key失效,导致缓存命中率下降,并且MySQL的压力迅速上升,甚至之间宕机

如何产生: 

1)redis之间挂了

redis宕机/redis集群模式下大量节点宕机

2)redis好着,但是Redis上的⼤量的key同时过期

可能之前短时间内设置了很多的key给redis,并且设置的过期时间是相同的

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

处理:

1)部署⾼可⽤的Redis集群,并且完善监控报警体系

2)不给key设置过期时间/设置过期时间的时候添加随机的因子(避免同一时刻)

缓存击穿(Cachebreakdown)

此处把breakdown翻译成"击穿",个⼈以为并⾮是⼀个好的选择.容易和缓存穿透混淆. 翻译成"瘫痪"或者"崩溃"也许更合适⼀些. 

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

处理:

  • 基于统计的方式发现热点key,并设置永不过期(往往需要服务器结构做出较大的调整)
  • 进⾏必要的服务降级.例如访问数据库的时候使⽤分布式锁,限制同时请求数据库的并发数

假如本身服务器的功能,有10个,但是在特定情况下,适当关闭一些不重要的功能,只保留核心功能(服务降级)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值