热点数据 & 冷数据
热点数据和冷数据是什么?
冷数据:大部分数据可能还没有再次访问到就已经被挤出内存,不仅占用内存,而且价值不大
热点数据:
比如我们的某 IM 产品,生日祝福模块,当天的寿星列表,缓存以后可能读取数十万次,热点数据,缓存才有价值
举个例子,某导航产品,我们将导航信息,缓存以后可能读取数百万次,数据更新前至少读取两次,缓存才有意义
这个是最基本的策略,如果缓存还没有起作用就失效了,那就没有太大价值了
那存不存在,修改频率很高,但是又不得不考虑缓存的场景呢?
有!比如,这个读取接口对数据库的压力很大,但是又是热点数据,这个时候就需要考虑通过缓存手段,减少数据库的压力
比如我们的某助手产品的,点赞数,收藏数,分享数等是非常典型的热点数据,但是又不断变化
此时就需要将数据同步保存到 Redis 缓存,减少数据库压力
缓存雪崩
当某一个时刻出现大规模的缓存失效的情况,那么就会导致大量的请求直接打在数据库上面,导致数据库压力巨大
如果在高并发的情况下,可能瞬间就会导致数据库宕机
这时候如果运维马上又重启数据库,马上又会有新的流量把数据库打死
解决方案:过期时间加随机数、互斥锁、多级缓存、部署集群
缓存击穿
缓存击穿是指一个高并发系统中,一个热点的缓存key突然失效(例如,缓存过期)
导致这个时刻所有的请求都会落到数据库上,从而引起数据库压力骤增,可能会导致数据库短时间内崩溃
这种情况下,缓存系统没有发挥应有的作用,反而因为缓存key的失效,导致数据库直接面临巨大的访问压力
解决方案:互斥锁、逻辑过期、缓存不过期、缓存自动续期
缓存穿透
指用户查询数据,在数据库没有,自然在缓存中也不会有
这样就导致用户查询的时候,在缓存中找不到,每次都要去数据库再查询一遍,然后返回空(相当于进行了两次无用的查询)
这样请求就绕过缓存直接查数据库,这也是经常提的缓存命中率问题
解决方案:布隆过滤器、缓存空值、查询校验
缓存预热
系统上线后,将相关的缓存数据直接加载到缓存系统
这样就可以避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!
解决方案示例:
直接写个缓存刷新页面,上线时手工操作下
数据量不大,可以在项目启动的时候自动进行加载
定时刷新缓存
缓存更新
除了缓存服务器自带的缓存失效策略之外(Redis 默认的有 6 种策略可供选择)
我们还可以根据具体的业务需求进行自定义的缓存淘汰,常见的策略有两种:
定时去清理过期的缓存
当有用户请求过来时,再判断这个请求所用到的缓存是否过期,过期的话就去底层系统得到新数据并更新缓存
两者各有优劣:
第一种的缺点是维护大量缓存的 key 是比较麻烦的
第二种的缺点就是每次用户请求过来都要判断缓存失效,逻辑相对比较复杂
具体用哪种方案,大家可以根据自己的应用场景来权衡
缓存降级
当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时
仍然需要保证服务还是可用的,即使是有损服务
系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级
降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如加入购物车、结算)
以参考日志级别设置预案:
一般:比如有些服务偶尔因为网络抖动或者服务正在上线而超时,可以自动降级
警告:有些服务在一段时间内成功率有波动(如在 95~100% 之间),可以自动降级或人工降级,并发送告警
错误:
比如可用率低于 90%,或者数据库连接池被打爆了
或者访问量突然猛增到系统能承受的最大阀值,此时可以根据情况自动降级或者人工降级
严重错误:比如因为特殊原因数据错误了,此时需要紧急人工降级
服务降级的目的,是为了防止 Redis 服务故障,导致数据库跟着一起发生雪崩问题
因此,对于不重要的缓存数据,可以采取服务降级策略
例如一个比较常见的做法就是,Redis 出现问题,不去数据库查询,而是直接返回默认值给用户
评论区