共计 2627 个字符,预计需要花费 7 分钟才能阅读完成。
缓存咱们常常应用,然而有时候咱们却会疏忽缓存中的一些问题。
咱们将从 生产环境的利用 的角度,去思考须要留神的一些异常情况,特地的是在 高并发 的场景下,如何让咱们的缓存在提供 高性能 反对的同时,去保 证数据的准确性 ,还有 零碎的稳定性。
首先来看第一个问题,看这张图,这里咱们引入的缓存的目标,就是用来帮忙数据库去挡掉大部分的读申请,从而晋升读申请的响应速度和并发能力。
如果有一段时间,因为种种原因,缓存的数据不在了。这个时候,这些读申请全副都间接落到数据库下面来,如果这个时候并发量很大,就很有可能会把数据库给压垮。数据库一垮基本上整个利用都会被拖垮了,更重大的话会造成一系列的连锁反应,影响到上下游零碎。
生产环节呈现缓存雪崩的几种状况
总结一下问题:因为缓存数据生效(或不存在),导致大量读申请间接拜访数据库,把数据库甚至利用拖垮。这个就是缓存雪崩问题。
能够看到这里问题的关键点,在于 大量的缓存数据生效(或不存在),个别在生产环节中,次要有这几种状况,可能会导致引起缓存雪崩问题:
状况一:
第一种状况可能是咱们自身就没有进行 提前预设置缓存,或者说有设置缓存,然而写入 redis 的数据还没来的及长久化,redis 服务异样重启,那么这种状况下就可能会导致缓存数据失落。
尽管说 Redis 提供了长久化机制,但它的两种长久化模式,RDB 和 AOF,都没方法百分之百保证数据不失落。
实际上在实战我的项目中,很多时候为了缩小对中间件的依赖,为了升高运维老本,或者为了晋升 Redis 性能等等,很多零碎都是不开启 Redis 长久化机制的,那么这样当 Redis 产生重启的话,缓存数据就全副清空了。
状况二:
还有一种状况就是,提前设置了缓存,然而 缓存的过期工夫设置过于集中,导致少量数据同时过期,所以咱们在应用 redis 的时候也不得不思考到这种状况的产生。
就拿一年一度的双十一购物节来说,如果马上就要到双十一零点,很快就会迎来一波抢购,这波商品工夫比拟集中的放入了缓存。假如缓存一个小时。那么到了凌晨一点钟的时候,这批商品的缓存就都过期了。而对这批商品的拜访查问,都落到了数据库上。对于数据库而言,就会产生周期性的压力波峰,如果没有一个好的解决计划,可能在缓存生效的一瞬间,数据库就扛不住压力挂掉了,进而导致其它关联的零碎被连累,最终导致整个零碎解体,这种状况就是咱们常说的缓存雪崩,设想下这种状况如果产生在双十一会产生如许重大的影响。所以咱们就得提前针对这种状况进行思考设计。
状况三:
最初还有一种状况,咱们都晓得为了保障较高的性价比,缓存的空间容量必然要小于后端数据库的数据总量。 随着要缓存的数据量越来越大,缓存空间就不可避免的会被写满。这个时候 redis 就会有一个缓存数据的 淘汰机制,如果咱们这个缓存淘汰机制设置得不是很正当就会大面积地淘掉正在应用的缓存,就会导致下面说的问题。
redis 的缓存淘汰策略是指在 Redis 用于缓存的内存不足时, 怎么解决。
这里咱们看下 redis 的两个参数
- 咱们能够通过设置 maxmemory 参数来设置内存的最大使用量(配置)
- 同时来配置 maxmemory-policy 参数: 抉择对应的内存淘汰规定(配置), 当内存不够用时, 会设置的内存淘汰规定
其中在 Redis 中有如下淘汰规定
针对这种状况,咱们能够联合我的项目的理论状况,通过指定适合的淘汰规定来防止无效的缓存数据失落。
然而这个只能略微缓解一下,如果利用中须要缓存的数据量十分大,这个时候能够通过 扩充集群的部署规模,来减少整个缓存组件的容量。
解决缓存雪崩的几种解决方案
下面就是三种次要的缓存生效的容易导致缓存雪崩的状况。
接下来咱们来看一下常见的几种解决缓存雪崩的计划:
首先联合业务的特点和场景,从业务角度登程,咱们来看一下有哪些优化伎俩。
针对下面提到的缓存集中生效这个场景,咱们能够采纳这样的思路来缓解:
- 扩散缓存生效工夫。
首先咱们能够采取不同分类商品,缓存不同周期。在同一分类中的商品,加上一个随机因子。这样能尽可能扩散缓存过期工夫,而且,热门类目标商品缓存工夫长一些,冷门类目标商品缓存工夫短一些,也能节俭缓存服务的资源。
- 热门数据不设置过期工夫
咱们能够针对一些热门商户和热门商品的数据,也就是零碎中最热门的数据,设置为数据永不过期。这样可这样能够保障这部分申请量很大的数据,始终可能从缓存中去获取数据。
- 提前预热缓存数据
还有一个策略,就是提前预热缓存数据。
什么叫缓存预热,缓存预热就是在系统启动之后,或者零碎运行期间定期地将一些缓存数据间接加载到缓存零碎,这样就能够防止等到用户申请的时候再去查询数据库,而后再将数据回写到缓存。
这种策略,除了适宜后面提到的零碎中最热那一部分数据,也适宜当零碎有营销流动的时候,去提前预热相干的数据,防止流动一开始的时候,霎时涌进来的流量把零碎冲垮。
缓存预热的思路个别是这样的:
当数据量不大的时候,咱们能够在工程启动的时候,就进行加载缓存动作;
如果数据量比拟大,那能够在运行期间通过定时工作脚本,去进行缓存的刷新;重点呢是优先保障热点数据可能提前加载到缓存。
这几个就是联合业务场景,从业务角度登程去优化的策略,然而光靠这些策略只能起到缓解的作用,还是不足以齐全保障咱们零碎稳固,咱们还是须要通过技术手段来进行保障。
除了下面咱们提到的 通过扩充集群规模去解决容量不够的问题 ,咱们接下来次要看一下针对 缓存生效 的状况,如何通过技术手段来避免零碎雪崩问题。
首先咱们能够 对数据库拜访减少限流 的解决,来爱护咱们的数据库,爱护咱们这个零碎的外围资源。
数据库它跟缓存组件不一样,它并不善于应答高并发的场景,它所能承载的并发量,是远小于缓存中间件的,那如果把拜访缓存的申请全副怼到数据库,分分钟就把数据库搞垮了,通过限流让零碎响应慢一点,总归比间接把零碎拖垮好一些。
还有一种形式,咱们能够进行 缓存降级。缓存降级是指缓存生效或缓存服务器挂掉的状况下,不去拜访数据库,间接返回默认的数据,从而防止数据库蒙受微小压力。
当然降级个别是对用户体验有损的,所以尽量减少降级对于业务的影响水平。
通过下面这些办法,基本上能够防止缓存雪崩问题。
作者:大熊,资深架构师
大型商业银行信息技术部负责项目组技术负责人,主攻 Java 大型分布式系统架构能力、分布式架构难点落地,熟练掌握多线程、高并发相干原理及中间件利用。同时负责多个我的项目的项目经理,也获得了 PMP 证书,在项目管理方面具备理论知识和实战经验。
本文由 mdnice 多平台公布