前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Redis面试(五):缓存异常(一)

Redis面试(五):缓存异常(一)

原创
作者头像
传说之下的花儿
发布2023-09-25 08:31:31
2920
发布2023-09-25 08:31:31
举报

4. 缓存异常[❤️]

缓存异常有四种类型,分别是 缓存穿透、缓存雪崩、缓存击穿、缓存和数据库的数据不一致。

4.1 缓存穿透

4.1.1 介绍

先来看一个常见的缓存使用方式:读请求来了,先查下缓存,缓存有值命中,就直接返回;缓存没命中,就去查数据库,然后把数据库的值更新到缓存,再返回。

缓存穿透:指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,进而给数据库带来压力。

通俗点说,读请求访问时,缓存和数据库都没有某个值,这样就会导致每次对这个值的查询请求都会穿透到数据库,这就是缓存穿透。

缓存穿透一般都是这几种情况产生的:

  • 业务不合理的设计,比如大多数用户都没开守护,但是你的每个请求都去缓存,查询某个userid查询有没有守护。
  • 业务/运维/开发失误的操作,比如缓存和数据库的数据都被误删除了。
  • 黑客非法请求攻击,比如黑客故意捏造大量非法请求,以读取不存在的业务数据。
4.1.2 解决方案
  1. 将无效的key存放进Redis中 当出现 Redis 查不到数据,数据库也查不到数据的情况,我们就把这个 key 保存到 Redis 中,设置 value="null",并设置其过期时间极短,后面再出现查询这个 key 的请求的时候,直接返回 null,就不需要再查询数据库了。 但这种处理方式是有问题的,假如传进来的这个不存在的 Key 值每次都是随机的,那存进 Redis 也没有意义。
  • 使用布隆过滤器快速判断数据是否存在。即一个查询请求过来时,先通过布隆过滤器判断值是否存在,存在才继续往下查。

布隆过滤器原理: 它由初始值为0的位图数组和N个哈希函数组成。 对一个key进行N个hash算法获取N个值,在比特数组中将这N个值散列后设定为1,然后查的时候如果特定的这几个位置都为1,那么布隆过滤器判断该key存在。 如果有不为1 的,那么这个key一定不存在,如果都为1,那么这个key可能存在。

如何选择这两种方案呢

针对一些恶意攻击,攻击带过来的大量 key 是随机,如果我们采用第一种方案就会缓存大量不存在 key 的数据,所以这种方案就不合适了,我们可以先对使用布隆过滤器方案进行过滤掉这些 key。所以,针对这种 key 异常多、请求重复率比较低的数据,优先使用第二种方案直接过滤掉。

而对于空数据的 key 有限的,重复率比较高的,则可优先采用第一种方式进行缓存。

4.2 缓存雪崩

4.2.1 介绍

缓存雪崩: 指缓存中数据大批量到过期时间,而查询数据量巨大,请求都直接访问数据库,引起数据库压力过大甚至宕机。

造成雪崩的可能

  • 采用了相同的过期时间:一般是由于大量数据同时过期造成的,对于这个原因,可通过均匀设置过期时间解决,即让过期时间相对离散一点。如采用一个较大固定值+一个较小的随机值,5小时+0到1800秒。
  • Redis 宕机:Redis 故障宕机也可能引起缓存雪奔。这就需要构造Redis高可用集群啦。
4.2.2 解决方案
  1. 事前:
    • 均匀过期:设置不同的过期时间,让缓存失效的时间尽量均匀,避免相同的过期时间导致缓存雪崩,造成大量数据库的访问。 如把每个 Key 的失效时间都加个随机值,setRedis(Key,value,time + Math.random() * 10000);,保证数据不会在同一时间大面积失效。
    • 分级缓存:第一级缓存失效的基础上,访问二级缓存,每一级缓存的失效时间都不同。
    • 热点数据缓存永远不过期。永不过期实际包含两层意思:
      • 物理不过期,针对热点 key 不设置过期时间
      • 逻辑过期,把过期时间存在 key 对应的 value 里,如果发现要过期了,通过一个后台的异步线程进行缓存的构建
    • 保证 Redis 缓存的高可用,防止 Redis 宕机导致缓存雪崩的问题。可以使用 主从 + 哨兵,Redis 集群来避免 Redis 全盘崩溃的情况。
  2. 事中:
    • 互斥锁:在缓存失效后,通过互斥锁或者队列来控制读数据写缓存的线程数量,比如某个 key 只允许一个线程查询数据和写缓存,其他线程等待。这种方式会阻塞其他的线程,此时系统的吞吐量会下降
    • 使用熔断机制,限流降级。当流量达到一定的阈值,直接返回 “系统拥挤” 之类的提示,防止过多的请求打在数据库上将数据库击垮,至少能保证一部分用户是可以正常使用,其他用户多刷新几次也能得到结果。
  3. 事后: 开启 Redis 持久化机制,尽快恢复缓存数据,一旦重启,就能从磁盘上自动加载数据恢复内存中的数据。

4.3 缓存击穿

4.3.1 介绍

缓存击穿: 指热点key在某个时间点过期的时候,而恰好在这个时间点对这个Key有大量的并发请求过来,从而大量的请求打到数据库。

与缓存雪崩的区别:

缓存雪奔是指数据库压力过大甚至宕机,缓存击穿只是大量并发请求到了DB数据库层面。可以认为击穿是缓存雪奔的一个子集吧。有些文章认为它俩区别在于击穿是针对某一热点key缓存,雪奔则是很多key。

4.3.2 解决方案

从两个方面解决,第一是否可以考虑热点 key 不设置过期时间,第二是否可以考虑降低打在数据库上的请求数量。

解决方案就有两种:

  • 使用互斥锁方案:缓存失效时,不是立即去加载db数据,而是先使用某些带成功返回的原子操作命令,如(Redis的setnx)去操作,成功的时候,再去加载db数据库数据和设置缓存。否则就去重试获取缓存。
  • “热点数据永不过期”,永不过期实际包含两层意思
    • 物理不过期,针对热点 key 不设置过期时间
    • 逻辑过期,把过期时间存在 key 对应的 value 里,如果发现要过期了,通过一个后台的异步线程进行缓存的构建

我正在参与2023腾讯技术创作特训营第二期有奖征文,瓜分万元奖池和键盘手表

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 4. 缓存异常[❤️]
    • 4.1 缓存穿透
      • 4.1.1 介绍
      • 4.1.2 解决方案
    • 4.2 缓存雪崩
      • 4.2.1 介绍
      • 4.2.2 解决方案
    • 4.3 缓存击穿
      • 4.3.1 介绍
      • 4.3.2 解决方案
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档