redis学习笔记27——缓存被污染了怎么办(代码片段)

qq_34132502 qq_34132502     2022-12-05     196

关键词:

在一些场景下,有些数据被访问的次数非常少,甚至只会被访问一次。当这些数据服务完访问请求后,如果还继续留存在缓存中的话,就只会白白占用缓存空间。这种情况,就是缓存污染

我们应用 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 字段,又进一步拆分成了两部分。

  1. ldt字段:lru字段的前16bit,表示数据访问的时间戳
  2. 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学习笔记24——替换策略:缓存满了怎么办(代码片段)

如果把所有的数据都放入缓存是否很好?并不,根据“八二原理”,80%的请求实际只访问了20%的数据,所以全部放入缓存的性价比很低。解决这个问题就涉及到缓存系统的一个重要机制,即缓存数据的淘汰机... 查看详情

redis学习笔记24——替换策略:缓存满了怎么办(代码片段)

如果把所有的数据都放入缓存是否很好?并不,根据“八二原理”,80%的请求实际只访问了20%的数据,所以全部放入缓存的性价比很低。解决这个问题就涉及到缓存系统的一个重要机制,即缓存数据的淘汰机... 查看详情

redis学习笔记10:redis缓存穿透和雪崩

        Redis缓存的使用,极大的提升了应用程序的性能和效率,特别是数据查询方面。但同时,它也带来了一些问题。其中,最要害的问题,就是数据的一致性问题,从严格意义上讲,这个问题无解。如果对数据的一致性要求很高,那... 查看详情

redis学习笔记10:redis缓存穿透和雪崩

        Redis缓存的使用,极大的提升了应用程序的性能和效率,特别是数据查询方面。但同时,它也带来了一些问题。其中,最要害的问题,就是数据的一致性问题,从严格意义上讲,这个问题无解。如果对数据的一致性要求很高,那... 查看详情

redis学习笔记23——旁路缓存:redis是如何工作的?(代码片段)

计算机系统中,默认有两种缓存:CPU里面的末级缓存,即LLC,用来缓存内存中的数据,避免每次从内存中存取数据;内存中的高速页缓存,即pagecache,用来缓存磁盘中的数据,避免每次从磁盘中... 查看详情

redis学习笔记23——旁路缓存:redis是如何工作的?(代码片段)

计算机系统中,默认有两种缓存:CPU里面的末级缓存,即LLC,用来缓存内存中的数据,避免每次从内存中存取数据;内存中的高速页缓存,即pagecache,用来缓存磁盘中的数据,避免每次从磁盘中... 查看详情

redis学习笔记--项目实践过程遇到的问题(代码片段)

怎么保证缓存和数据库数据的一致性?1.设置缓存过期时间2.数据的更新操作,先删除缓存,再更新数据库。如果我们先更新数据库,会导致其他业务线程读到缓存中的脏数据,所以数据库的更新操作一般是先... 查看详情

redis学习笔记--项目实践过程遇到的问题(代码片段)

怎么保证缓存和数据库数据的一致性?1.设置缓存过期时间2.数据的更新操作,先删除缓存,再更新数据库。如果我们先更新数据库,会导致其他业务线程读到缓存中的脏数据,所以数据库的更新操作一般是先... 查看详情

尚硅谷redis学习笔记--redis应用问题解决(代码片段)

1.缓存穿透1.1问题描述key对应的数据在数据源并不存在,每次针对此key的请求从缓存获取不到,请求都会压到数据源,从而可能压垮数据源。比如用一个不存在的用户id获取用户信息,不论缓存还是数据库都没有&#x... 查看详情

学习笔记——redis数据类型(zset)(代码片段)

2023-01-27一、redis数据类型(ZSet)redis中的zset是一个有序集合,是一个没有重复元素的字符串集合。注意:①zset中的每个成员都关联了一个评分,这个评分是从最低分到最高分的方式进行排序的。②集合的成员是唯一的,但是评... 查看详情

redis学习笔记(代码片段)

学习内容:数据库发展史(单机MySql的演进),NoSql,Redis的概念数据库发展史,关系数据库和非关系数据库的关系和差别,Redis基本命令,基本数据类型,事务锁,集成Java(Jedis,SpringBoot自定义模板,封装util工具类等),持久化方式,发布订阅,... 查看详情

缓存机制

缓存污染:缓存污染降低了缓存的使用率,把不常用的数据读取到缓存,同时会把常用的数据移出缓存,这样会直接降低系统的数据命中率回避策略使用缓存淘汰算法(如:LFU, LRU)可以有效降低缓存污染的现象。对缓存机... 查看详情

[爬虫学习笔记]memorycache缓存的用法学习

...带的Cache之间,考虑到部署问题,最终选择了后者,之前在学习Web及开发的过程中用过System.Web.Caching.Cache这个类库,但是这次的爬虫程序我打算部署为桌面软件,所以选用了System.Runtime.Cach 查看详情

redis学习笔记—客户端通讯协议resp(代码片段)

Redis制定了RESP(REdisSerializationProtocol,Redis序列化协议)实现客户端与服务端的正常交互,这种协议简单高效,既能够被机器解析,又容易被人类识别发送命令格式RESP的规定一条命令的格式如下,CRLF代... 查看详情

学习笔记redis中有序集合zset的实现原理——跳表(代码片段)

面试的时候被问到了有序集合zset的实现原理,本以为是基于红黑树实现的,其实是基于跳表(skipList)实现的。本文主要讲解什么是跳表,它是怎么查找、插入和删除元素的,相比于红黑树它有哪些优劣。... 查看详情

redis学习笔记26——缓存异常:如何解决缓存雪崩击穿穿透问题?

缓存雪崩缓存雪崩是指大量的应用请求无法在Redis缓存中进行处理,紧接着,应用将大量请求发送到数据库层,导致数据库层的压力激增。缓存雪崩一般有两个原因导致:1、缓存中有大量数据同时过期解决方法... 查看详情

redis学习笔记26——缓存异常:如何解决缓存雪崩击穿穿透问题?

缓存雪崩缓存雪崩是指大量的应用请求无法在Redis缓存中进行处理,紧接着,应用将大量请求发送到数据库层,导致数据库层的压力激增。缓存雪崩一般有两个原因导致:1、缓存中有大量数据同时过期解决方法... 查看详情

redis学习笔记25——缓存异常:如何解决缓存和数据库的数据不一致问题?

缓存和数据库的数据不一致是如何发生的?一致性包含了两种情况:缓存中有数据,那么,缓存的数据值需要和数据库中的值相同;缓存中本身没有数据,那么,数据库中的值必须是最新值。发生的原... 查看详情