性能优化--缓存的回收策略优化思路雪崩

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


以上是关于性能优化--缓存的回收策略优化思路雪崩的主要内容,如果未能解决你的问题,请参考以下文章

高并发存储优化篇:诸多策略,缓存为王

MySql性能优化查询优化

程序性能优化策略

程序性能优化策略

前端性能优化之HTTP缓存策略

常见性能优化策略的总结(转)