“Redis常见面试题(持续更新)”

缓存三兄弟

缓存穿透

查询一个不存在的数据,redis查询不到,再查询mysql也查询不到,也不会直接写入缓存,导致每次请求都查询数据库
有人恶意通过发送大量不存在的请求,导致数据库宕机

解决方案一:缓存

redis缓存空数据,查询返回的数据为空,仍然把这个空结果进行缓存
优点:简单
缺点:消耗内存,可能会发生不一致的问题

解决方案二:布隆过滤器

布隆过滤器,在查询redis前,先查询布隆过滤器,检索一个元素是否在一个集合中
布隆过滤器原理:
存储数据:通过对数据进行若干个哈希函数计算得到哈希值,将bitmap对应位置的值置为一
查询数据:使用相同的哈希函数获取哈希值,判断对应位置是否都为一,如果不全为一说明不存在
注意:“不存在一定不存在,存在不一定存在
误判率:作为一个参数可以被设置,数组越小误判率越大,数组越大误判率越小,但响应的内存占用越大
优点:占用内存少,没有多余key
缺点:实现复杂,存在误判

缓存击穿

给某一个热点key设置了过期时间,当key过期时,恰好这时这个时间点对这个key有大量的并发请求,可能导致压垮数据库

解决方案一:互斥锁

互斥锁,当线程查询redis失败后,不立刻去请求数据库,而是使用如Redis的setnx去设置一个互斥锁,当获取锁成功时才进行查询,写入缓存完成后在释放锁
优点:可以保证redis和数据库的强一致性
缺点,性能差

解决方案二:自动续期

缓存击穿是由于热点key过期导致的,所以可以使用一个job给热点key自动更新缓冲,重新设置过期时间为30分钟

解决方案三:永不过期

对于很多热门key,其实是可以不用设置过期时间,让其永久有效的。比如参与秒杀活动的热门商品,由于这类商品id并不多,在缓存中我们可以不设置过期时间。在秒杀活动开始前,我们先用一个程序提前从数据库中查询出商品的数据,然后同步到缓存中,提前做预热
等压力过去之后,再手动删除这些无用的缓存

缓存雪崩

同时有多个key失效或者redis服务宕机,导致大量请求到达数据库,给数据库带来巨大压力

解决方案一:过期时间加随机数

为了解决缓存雪崩问题,我们首先要尽量避免缓存同时失效的情况发生,可以在过期时间上加上一个随机数,这样即使在高并发的情况下,多个请求同时设置过期时间,由于有随机数的存在,也不会出现太多相同的过期key。

解决方案二:高可用

针对缓存服务器down机的情况,在前期做系统设计时,可以做一些高可用架构。比如:如果使用了redis,可以使用哨兵模式,或者集群模式,避免出现单节点故障导致整个redis服务不可用的情况。
使用哨兵模式之后,当某个master服务下线时,自动将该master下的某个slave服务升级为master服务,替代已下线的master服务继续处理请求。

作者

Zhangmingyu

发布于

2024-10-14

更新于

2025-06-04

许可协议

You need to set install_url to use ShareThis. Please set it in _config.yml.
You forgot to set the business or currency_code for Paypal. Please set it in _config.yml.

评论

You forgot to set the shortname for Disqus. Please set it in _config.yml.