Redis的常见的问题(穿透、雪崩、击穿、热key、大key、不一致)

缓存穿透

  • 产生的原因:请求不存在的资源(DB中不存在,redis中更不存在)。例如,一大批ID为-0的数据去访问请求(DB中不存在),或者是恶意攻击(大量高并发),就可能会出现缓存穿透的情况。因为数据库中不存在ID为-0的数据,那么redis中更不存在,大量的数据就可能会把DB打垮。如图所示:

在这里插入图片描述

  • 解决办法:
    1、对空值进行缓存:对于DB中没有的数据,进行redis缓存,假如上述的-0数据在DB中没有,那么可以在redis中对-=对数据进行空值缓存(key = -0,value = 0),那么当请求过来的时候,会返回一个null值。避免将大量的数据抛到DB层,对数据库造成巨大的压力,保持数据库正常运行。

    2、某些数据在业务层进行拦截:在java层可以过滤掉一些恶意数据,不向redis里面穿数据,例如DtoCheckUtils.check()。对于dto传入的数据进行检查过滤。

    3、实时监控: 对redis进行实时监控,当发现redis中的命中率下降的时候进行原因的排查,配合运维人员对访问对象和访问数据进行分析查询,从而进行黑名单的设置限制服务(拒绝黑客攻击)

    4、使用布隆过滤器:使用布隆过滤器快速判断数据是否存在,避免从数据库中查询数据是否存在,减轻数据库压力。
    使用BitMap作为布隆过滤器,将目前所有可以访问到的资源通过简单的映射关系放入到布隆过滤器中(哈希计算),当一个请求来临的时候先进行布隆过滤器的判断,如果有那么才进行放行,否则就直接拦截
    在这里插入图片描述

缓存雪崩

  • 产生原因:大量的应用请求无法在 Redis 缓存中进行处理,紧接着,应用将大量请求发送到数据库层,导致数据库层的压力激增。比如设定token是在零点过期,redis中的大部分数据都被清空了,但是这时有大量的并发请求,那么redis就无法进行有效的响应(命中率急剧下降),请求就都打到DB上了,到时DB直接崩溃。
    在这里插入图片描述

  • 解决办法:
    1、将失效时间分散开:避免给大量的数据设置相同的过期时间。

 	如果业务层的确要求有些数据同时失效,你可以在用 EXPIRE 命令给每个数据设置过期时间时,给这些数据的过期时间增加一个较小的随机数(例如,随机增加 1~3 分钟),这样一来,不同数据的过期时间有所差别,但差别又不会太大,既避免了大量数据同时过期,同时也保证了这些数据基本在相近的时间失效,仍然能满足业务需求。

2、通过服务降级,来应对缓存雪崩。

所谓的服务降级,是指发生缓存雪崩时,针对不同的数据采取不同的处理方式。

当业务应用访问的是非核心数据,暂时停止从缓存中查询这些数据,而是直接返回预定义信息、空值或是错误信息;
当业务应用访问的是核心数据时,仍然允许查询缓存,如果缓存缺失,也可以继续通过数据库读取。

这样一来,只有部分过期数据的请求会发送到数据库,数据库的压力就没有那么大了。下面这张图显示的是服务降级时数据请求的执行情况,你可以看下。

在这里插入图片描述

缓存击穿

  • 产生原因:redis缓存中没有数据,但是数据库中有数据,大量的请求访问redis中找不到数据,直接打入数据库,可能造成数据库压力太大,数据库崩溃,叫缓存击穿。
    在这里插入图片描述

  • 解决方式
    1、调整数据缓存,不给热点数据设置过期时间,一直保留、或者定期更新缓存。例如一些热点的词汇查找、淘宝活动排行榜等一些高访问请求的接口。
    2、使用redis的setnx互斥锁先进行判断,这样其他线程就处于等待状态,保证不会有大并发操作去操作数据库。或者采用分布式锁,让一个线程去访问数据库,将数据添加到缓存中后,其他线程直接从缓存中获取。

热key问题(hot key)

  • 产生原因:单个固定key的请求打在了一台redis节点上,有大量的请求去访问redis缓存数据库中的某一个key值的时候,压垮缓存数据库。例如,鹿晗官宣恋情,微博造成了崩溃,可能就是造成了redis服务器宕机,在redis服务宕机之后,这个请求就都打到了DB上,导致数据库也崩溃。
    热key问题就是某个瞬间有大量的请求去访问Redis上某个固定的key,导致缓存击穿,请求都打到了DB上,压垮了缓存服务和DB服务,从而影响到应用服务可用的可用性;

  • 热key的解决方案:
    1、使用二级缓存:在该redis服务器之前再做一层缓存,如果有大量的热点请求打来时,会直接从二级缓存调取,不会直接打到redis层。
    2、将热key分散到不同的服务器中。不要让固定key老是走到同一台redis节点上;我们把这个key,在多个redis节点上都备份一份即可,在有热key请求进来的时候,我们就在有备份的redis上随机选取一台,进行访问取值,返回数据,就能缓解redis单点热key的查询压力。

具体解决方案如下网址:
https://blog.csdn.net/minghao0508/article/details/123972442

大key问题

  • 产生原因:通俗易懂的讲,Big Key就是某个key对应的value很大,占用的redis空间很大,本质上是大value问题。key往往是程序可以自行设置的,value往往不受程序控制,因此可能导致value很大。edis中这些Big Key对应的value值很大,在序列化/反序列化过程中花费的时间很大,因此当我们操作Big Key时,通常比较耗时,这就可能导致redis发生阻塞,从而降低redis性能。例如,一个key上存的是一个1,2g的全景图。
  • 解决方式:
    1、对大key进行拆分:将一个Big Key拆分为多个key-value这样的小Key,并确保每个key的成员数量或者大小在合理范围内,然后再进行存储,通过get不同的key或者使用mget批量获取。
    2、对大key进行清理:在Redis 4.0之前,不要直接删除,会阻塞命令,利用scan命令迭代大Key的元素,分批删除。 在Redis 4.0及之后,采用lazy free机制,使用unlink命令假删除大key,之后后台线程进行异步惰性删除。
    3、使用hash存储:当key之间存在联系时,例如同一个对象的属性,使用Hash的field代替原有的key。
    4、压缩大key的值value:压缩到合理范围内。

数据不一致问题

  • 产生原因:主从同步有延时,延时期间读从库,可能读到不一致的数据。数据库与缓存库中的数据不一致。
    在这里插入图片描述

1)服务发起了一个写请求;
2)服务又发起了一个读请求,此时同步未完成,读到一个不一致的脏数据;
3)数据库主从同步最后才完成。

  • 解决方式:
    1、延迟双删:先删除缓存数据,再写数据库,在数据库数据写完之后,再次删除缓存数据,再更新缓存库。
具体方式实现链接:
https://huaweicloud.csdn.net/637f7741dacf622b8df84e03.html?spm=1001.2101.3001.6650.14&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Eactivity-14-125241401-blog-115868702.pc_relevant_3mothn_strategy_and_data_recovery&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7Eactivity-14-125241401-blog-115868702.pc_relevant_3mothn_strategy_and_data_recovery&utm_relevant_index=22

2、高并发下解决方案,使用内存队列解决,把 读请求 和 写请求 都放到队列中,按顺序执行(即串行化的方式解决)。(要定义多个队列,不同的商品放到不同的队列中,换言之,同一个队列中只有一类商品)

缓存穿透与缓存击穿的区别

官方:缓存穿透是访问一个不存在的key,缓存不起作用,请求会穿透到DB,流量大时DB会挂掉。缓存击穿是访问一个存在的key,在缓存过期的一刻,同时有大量的请求,这些请求都会击穿到DB,造成瞬时DB请求量大、压力骤增。缓存穿透 访问一个不存在的key,缓存不起作用,请求会穿透到DB,流量大时DB会挂掉。

轮询机制

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值