文档目录
一、缓存概念
缓存是一个机制,用于存储最近访问的数据,以便下一次请求相同的数据时可以更快地获取。通常,缓存位于计算机内存中,可以是硬件缓存或软件缓存。缓存可以存储各种类型的数据,包括文本、图像、网站页面等等。在互联网上,缓存通常用于加速网站的加载速度,减少服务器负载,提高用户体验。
简而言之:一方面为了减少数据库的读数据库的压力,一方面为了提高接口响应的效率,会把一部分数据放置在内存中,对这部分数据设置过期时间,数据过期之前供接口读取这些数据。这样一来,既减少了数据库压力,也减少了接口响应时长,一举多得。
二、缓存使用方式
当有读请求访问时,程序会先查缓存
如果缓存中有目标值,就直接返回缓存中查到的目标值;
如果缓存中查不到,就去查数据库,然后把数据库的值更新到缓存,再返回读取缓存,
总之,最终的数据肯定时从缓存中读取出来的
如下图
三、缓存穿透
简单来说,就是缓存和数据库中都没有目标值
缓存中查不到会去数据库中查,数据库中也没有,返回空值,乍一看感觉这个逻辑似乎也合理,
但是如果这样的情况非常频繁,或者遭到了请求攻击,那么查缓存,查数据库的操作就会一直执行,循环往复,这样数据库压力过载很容易宕机。
总结:读请求访问时,缓存和数据库都没有找到目标值,这样就会导致每次对这个值的查询请求都会穿透到数据库,这就是缓存穿透。
如下图
1、缓存穿透产生几种情况
- 业务不合理的设计,比如大多数用户都没开守护,但是你的每个请求都去缓存,查询某个userid查询有没有守护。
- 业务/运维/开发失误的操作,比如缓存和数据库的数据都被误删除了。
- 黑客非法请求攻击,比如黑客故意捏造大量非法请求,以读取不存在业务数据。
2、避免产生缓存穿透的几种方式
- 如果是非法请求,我们在API入口,对参数进行校验,过滤非法值。
- 如果查询数据库为空,我们可以给缓存设置个空值,或者默认值。但是如有有写请求进来的话,需要更新缓存哈,以保证缓存一致性,同时,最后给缓存设置适当过期时间。(业务上比较常用,简单有效)
- 使用布隆过滤器或者布谷鸟过滤器快速判断数据是否存在。即一个查询请求过来时,先通过布隆过滤器或者布谷鸟过滤器判断值是否存在,存在才继续往下查。
四、缓存雪崩
指缓存中数据大批量到过期时间,而查询数据量巨大,请求都直接访问数据库,引起数据库压力过大甚至宕机。
如下图
解决缓存雪崩的方式
- 缓存雪奔一般是由于大量数据同时过期造成的,对于这个原因,可通过均匀设置过期时间解决,即让过期时间相对离散一点。如采用一个较大固定值+一个较小的随机值,5小时+0到1800秒酱紫。
- Redis故障宕机也可能引起缓存雪奔。这就需要构造Redis高可用集群啦。
五、缓存击穿
指缓存中某个key在某个时间点过期时候,而恰好在这个时间点对这个Key有大量的并发请求过来,从而大量的请求打到数据库。
如下图
1、缓存击穿和缓存雪崩的区别
缓存击穿看着有点像缓存雪崩,其实它两区别是,缓存雪崩是指数据库压力过大甚至宕机,缓存击穿只是大量并发请求到了DB数据库层面。可以认为击穿是缓存雪崩的一个子集吧。也可以认为它俩区别,是区别在于击穿针对某一热点key缓存,雪崩则是很多key。
2、缓存击穿的解决方案
- 使用互斥锁方案:缓存失效时,不是立即去加载db数据,而是先使用某些带成功返回的原子操作命令,如(Redisetnx)去操作,成功的时候,再去加载db数据库数据和设置缓存。否则就去重试获取缓存。
- 永不过期:是指没有设置过期时间,但是热点数据快要过期时,异步线程去更新和设置过期时间。
备注
本文根据掘金博主**独爱竹子的功夫熊猫**文章改进
博主文章链接 https://juejin.cn/post/7276692859968127035