Redis学习笔记27——缓存被污染了怎么办
Posted qq_34132502
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Redis学习笔记27——缓存被污染了怎么办相关的知识,希望对你有一定的参考价值。
在一些场景下,有些数据被访问的次数非常少,甚至只会被访问一次。当这些数据服务完访问请求后,如果还继续留存在缓存中的话,就只会白白占用缓存空间。这种情况,就是缓存污染。
我们应用 Redis 缓存时,如果能缓存会被反复访问的数据,那就能加速业务应用的访问。但是,如果发生了缓存污染,那么,缓存对业务应用的加速作用就减少了。
如何解决缓存污染问题
我们很容易就可以想到了各种缓存淘汰策略,那这些策略的效果如何?
如果这8种策略(noeviction、volatile-random、volatile-ttl、volatile-lru、volatile-lfu、allkeys-lru、allkeys-random 和 allkeys-lfu ),如果按照算法来分,可以分成四组。
- random
- ttl
- LRU
- LFU
random
们都是采用随机挑选数据的方式,来筛选即将被淘汰的数据。
毋庸置疑,在避免缓存污染的问题上效果很有限
TTL
volatile-ttl 针对的是设置了过期时间的数据,把这些数据中剩余存活时间最短的筛选出来并淘汰掉。
所以,除了在明确知道数据被再次访问的情况下,这种策略并不能应对污染问题。
LRU
LRU 策略的核心思想:如果一个数据刚刚被访问,那么这个数据肯定是热数据,还会被再次访问。
但是,因为只看数据的访问时间,使用 LRU 策略在处理扫描式单次查询操作时,无法解决缓存污染。所谓的扫描式单次查询操作,就是指应用对大量的数据进行一次全体读取,每个数据都会被读取,而且只会被读取一次。此时,因为这些被查询的数据刚刚被访问过,所以 lru 字段值都很大。
LFU
为了应对扫描式缓存污染问题,Redis 从 4.0 版本开始增加了 LFU 淘汰策略。
与 LRU 策略相比,LFU 策略中会从两个维度来筛选并淘汰数据:一是,数据访问的时效性(访问时间离当前时间的远近);二是,数据的被访问次数。
LFU策略
LFU 缓存策略是在 LRU 策略基础上,为每个数据增加了一个计数器,来统计这个数据的访问次数。当使用 LFU 策略筛选淘汰数据时,首先会根据数据的访问次数进行筛选,把访问次数最低的数据淘汰出缓存。如果两个数据的访问次数相同,LFU 策略再比较这两个数据的访问时效性,把距离上一次访问时间更久的数据淘汰出缓存。
Redis 在实现 LFU 策略的时候,只是把原来 24bit 大小的 lru 字段,又进一步拆分成了两部分。
- ldt字段:lru字段的前16bit,表示数据访问的时间戳
- counter字段:lru字段的后8bit,表示数据访问的次数
总的来说,当 LFU 策略筛选数据时,Redis 会在候选集合中,根据counter
字段进行淘汰。当访问次数相同时,再根据ldt
时间戳大小,选择访问时间最久远的数据进行淘汰。
counter的非线性增加
这时出现了一个问题,8bit的counter
字段的最大值是255,访问次数超过255了该怎么办?
其实,在实现 LFU 策略时,Redis 并没有采用数据每被访问一次,就给对应的 counter 值加 1 的计数规则,而是采用了一个配置项lfu_log_factor
(大于等于0),将其非线性化,以控制计数器增加的速度,其值越大,counter
到达255的速度越慢。
counter的衰减机制
应用负载的情况是很复杂的,在一些场景下,有些数据在短时间内被大量访问后就不会再被访问了。那么再按照访问次数来筛选的话,这些数据会被留存在缓存中,但不会提升缓存命中率。为此,Redis 在实现 LFU 策略时,还设计了一个 counter 值的衰减机制。
LFU 策略使用衰减因子配置项lfu_decay_time
来控制访问次数的衰减。其值越大,衰减的越慢。
小结
在实际业务应用中,LRU 和 LFU 两个策略都有应用。LRU 和 LFU 两个策略关注的数据访问特征各有侧重LRU
策略更加关注数据的时效性,而LFU
策略更加关注数据的访问频次。通常情况下,实际应用的负载具有较好的时间局部性,所以 LRU 策略的应用会更加广泛。但是,在扫描式查询的应用场景中,LFU 策略就可以很好地应对缓存污染问题了,建议你优先使用。
以上是关于Redis学习笔记27——缓存被污染了怎么办的主要内容,如果未能解决你的问题,请参考以下文章