性能优化--缓存的回收策略优化思路雪崩
Posted changyandou
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了性能优化--缓存的回收策略优化思路雪崩相关的知识,希望对你有一定的参考价值。
缓存,本质上是为了协调两个速度差异非常大的组件,通过加入一个中间层,将常用的数据存放在相对高速的设备中。
缓存可能是软件中使用最多的优化技术了,比如:在最核心的 CPU 中,就存在着多级缓存;为了消除内存和存储之间的差异,各种类似 Redis 的缓存框架更是层出不穷。
缓存一般是比较昂贵的组件,容量是有限制的,设置得过小,或者过大,都会影响缓存性能:
缓存空间过小,就会造成高命中率的元素被频繁移出,失去了缓存的意义;
缓存空间过大,不仅浪费宝贵的缓存资源,还会对垃圾回收产生一定的压力。
缓存的大小是有限的,满了以后怎么办?这就需要回收策略进行处理:
(1)第一种回收策略基于容量
这个比较好理解,也就是说如果缓存满了,就会按照 LRU 算法来移除其他元素。
(2)第二种回收策略基于时间
一种方式是,通过 expireAfterWrite 方法设置数据写入以后在某个时间失效;
另一种是,通过 expireAfterAccess 方法设置最早访问的元素,并优先将其删除。
(3)第三种回收策略基于 JVM 的垃圾回收
我们都知道对象的引用有强、软、弱、虚等四个级别,通过 weakKeys 等函数即可设置相应的引用级别。当 JVM 垃圾回收的时候,会主动清理这些数据。
关于第三种回收策略,有一个高频面试题:如果你同时设置了 weakKeys 和 weakValues函数,LC 会有什么反应?
答案:如果同时设置了这两个函数,它代表的意思是,当没有任何强引用,与 key 或者 value 有关系时,就删掉整个缓存项。这两个函数经常被误解。
缓存优化的一般思路:
一般,缓存针对的主要是读操作。当你的功能遇到下面的场景时,就可以选择使用缓存组件进行性能优化:
存在数据热点,缓存的数据能够被频繁使用;
读操作明显比写操作要多;
下游功能存在着比较悬殊的性能差异,下游服务能力有限;
加入缓存以后,不会影响程序的正确性,或者引入不可预料的复杂性。
缓存组件和缓冲类似,也是在两个组件速度严重不匹配的时候,引入的一个中间层,但它们服务的目标是不同的:
缓冲,数据一般只使用一次,等待缓冲区满了,就执行 flush 操作;
缓存,数据被载入之后,可以多次使用,数据将会共享多次。
缓存最重要的指标就是命中率,有以下几个因素会影响命中率。
(1)缓存容量
缓存的容量总是有限制的,所以就存在一些冷数据的逐出问题。但缓存也不是越大越好,它不能明显挤占业务的内存。
(2)数据集类型
如果缓存的数据是非热点数据,或者是操作几次就不再使用的冷数据,那命中率肯定会低,缓存也会失去了它的作用。
(3)缓存失效策略
缓存算法也会影响命中率和性能,目前效率最高的算法是 Caffeine 使用的 W-TinyLFU 算法,它的命中率非常高,内存占用也更小。新版本的 spring-cache,已经默认支持 Caffeine。
缓存雪崩:
缓存是用来对系统加速的,后端的数据库只是数据的备份,而不是作为高可用的备选方案。当缓存系统出现故障,流量会瞬间转移到后端的数据库。过不了多久,数据库将会被大流量压垮挂掉,这种级联式的服务故障,可以形象地称为雪崩。
雪崩怎么形成?首先是部分缓存实例宕机,导致缓存命中率(Cache Hit Rate)下降,大量的请求落到后端存储上,导致后端存储过载,也出现宕机。
这时就会出现连锁反应,形成雪崩现象。后端存储就算重新启动起来,又会继续被巨大的用户请求压垮,整个系统怎么启动也启动不了。
应该怎么应对雪崩?最简单的办法,是后端存储自己要有过载保护能力。一旦并发的请求超过预期,就要丢弃部分请求,以减少压力。
参考:
https://www.fangbangxin.com/article/index/14986
https://t10.lagounews.com/7R78RjRkcY60D
https://t1.lagounews.com/7R87RsRdcYB69
以上是关于性能优化--缓存的回收策略优化思路雪崩的主要内容,如果未能解决你的问题,请参考以下文章