Redis 面试常见问答

什么是缓存雪崩?怎么解决?

缓存雪崩是指缓存中数据大批量到过期时间,而查询数据量巨大,引起数据库压力过大甚至down机。和缓存击穿不同的是,缓存击穿指并发查同一条数据。

如何解决呢?

  • 对缓存做高可用,防止缓存宕机。
  • 使用断路器,如果缓存宕机,为了防止系统全部宕机,限制部分流量进入DB,保证部分可用,其余的请求返回断路器的默认值。
  • 缓存数据的过期时间设置随机,防止同一时间大量数据过期现象发生。
  • 如果缓存数据库是分布式部署,将热点数据均匀分布在不同的缓存数据库中。
  • 设置热点数据永远不过期。

什么是缓存穿透?怎么解决?

缓存穿透是指缓存和数据库中都没有的数据,而用户不断发起请求,如发起为id为“-1”的数据或id为特别大不存在的数据。这时的用户很可能是攻击者,攻击会导致数据库压力过大。

如何解决呢?

  • 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
  • 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击。

什么是缓存击穿?怎么解决?

缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。

如何解决呢?

  • 设置热点数据永远不过期。
  • 可以在这些请求代码加上双重检查锁。但是那个阶段的请求会变慢。

什么是缓存并发竞争?怎么解决?

多个客户端写一个 key,如果顺序错了,数据就不对了。但是顺序我们无法控制。

如何解决呢?

使用分布式锁,例如 zk,同时加入数据的时间戳。同一时刻,只有抢到锁的客户端才能写入,同时,写入时,比较当前数据的时间戳和缓存中数据的时间戳。

什么是缓存和数据库双写不一致?怎么解决?

连续写数据库和缓存,但是操作期间,出现并发了,数据不一致了。

通常,更新缓存和数据库有以下几种顺序:

  • 先更新数据库,再更新缓存。
  • 先删缓存,再更新数据库。
  • 先更新数据库,再删除缓存。

先更新数据库,再更新缓存

这么做的问题是:当有 2 个请求同时更新数据,那么如果不使用分布式锁,将无法控制最后缓存的值到底是多少。也就是并发写的时候有问题

先删缓存,再更新数据库

这么做的问题:如果在删除缓存后,有客户端读数据,将可能读到旧数据,并有可能设置到缓存中,导致缓存中的数据一直是老数据

解决方案:延时双删策略,可将1秒内缓存脏数据,再次删除。最后一步的删除通常是异步操作,就是防止有客户端读取的时候设置了旧值。

先更新数据库,再删除缓存

这个实际是常用的方案,但是有很多人不知道,这里介绍一下,这个叫 Cache Aside Pattern,老外发明的。如果先更新数据库,再删除缓存,那么就会出现更新数据库之前有瞬间数据不是很及时。

同时,如果在更新之前,缓存刚好失效了,读客户端有可能读到旧值,然后在写客户端删除结束后再次设置了旧值,非常巧合的情况。

有 2 个前提条件:缓存在写之前的时候失效,同时,在写客户端删除操作结束后,放置旧数据 —— 也就是读比写慢。甚至有的写操作还会锁表。

所以,这个很难出现,但是如果出现了怎么办?使用异步延时双删!。

还有一种可能,如果执行更新数据库,准备执行删除缓存时,服务挂了,执行删除失败怎么办???

简单点的方法就是使用消息队列重试删除:

更好的方案:通过订阅数据库的 binlog 来删除

 

参考:

 

posted @ 2021-11-28 07:25  残城碎梦  阅读(32)  评论(0编辑  收藏  举报