Redis 核心技术与实战
蒋德钧
中科院计算所副研究员
79224 人已学习
新⼈⾸单¥68
登录后,你可以任选4讲全文学习
课程目录
已完结/共 53 讲
开篇词 (1讲)
实践篇 (28讲)
Redis 核心技术与实战
15
15
1.0x
00:00/00:00
登录|注册

27 | 缓存被污染了,该怎么办?

你好,我是蒋德钧。
我们应用 Redis 缓存时,如果能缓存会被反复访问的数据,那就能加速业务应用的访问。但是,如果发生了缓存污染,那么,缓存对业务应用的加速作用就减少了。
那什么是缓存污染呢?在一些场景下,有些数据被访问的次数非常少,甚至只会被访问一次。当这些数据服务完访问请求后,如果还继续留存在缓存中的话,就只会白白占用缓存空间。这种情况,就是缓存污染。
当缓存污染不严重时,只有少量数据占据缓存空间,此时,对缓存系统的影响不大。但是,缓存污染一旦变得严重后,就会有大量不再访问的数据滞留在缓存中。如果这时数据占满了缓存空间,我们再往缓存中写入新数据时,就需要先把这些数据逐步淘汰出缓存,这就会引入额外的操作时间开销,进而会影响应用的性能。
今天,我们就来看看如何解决缓存污染问题。

如何解决缓存污染问题?

要解决缓存污染,我们也能很容易想到解决方案,那就是得把不会再被访问的数据筛选出来并淘汰掉。这样就不用等到缓存被写满以后,再逐一淘汰旧数据之后,才能写入新数据了。而哪些数据能留存在缓存中,是由缓存的淘汰策略决定的。
到这里,你还记得咱们在第 24 讲一起学习的 8 种数据淘汰策略吗?它们分别是 noeviction、volatile-random、volatile-ttl、volatile-lru、volatile-lfu、allkeys-lru、allkeys-random 和 allkeys-lfu 策略。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结
仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Redis 核心技术与实战》
新⼈⾸单¥68
立即购买
登录 后留言

全部留言(40)

  • 最新
  • 精选
  • Kaito
    使用了 LFU 策略后,缓存还会被污染吗? 我觉得还是有被污染的可能性,被污染的概率取决于LFU的配置,也就是lfu-log-factor和lfu-decay-time参数。 1、根据LRU counter计数规则可以得出,counter递增的概率取决于2个因素: a) counter值越大,递增概率越低 b) lfu-log-factor设置越大,递增概率越低 所以当访问次数counter越来越大时,或者lfu-log-factor参数配置过大时,counter递增的概率都会越来越低,这种情况下可能会导致一些key虽然访问次数较高,但是counter值却递增困难,进而导致这些访问频次较高的key却优先被淘汰掉了。 另外由于counter在递增时,有随机数比较的逻辑,这也会存在一定概率导致访问频次低的key的counter反而大于访问频次高的key的counter情况出现。 2、如果lfu-decay-time配置过大,则counter衰减会变慢,也会导致数据淘汰发生推迟的情况。 3、另外,由于LRU的ldt字段只采用了16位存储,其精度是分钟级别的,在counter衰减时可能会产生同一分钟内,后访问的key比先访问的key的counter值优先衰减,进而先被淘汰掉的情况。 可见,Redis实现的LFU策略,也是近似的LFU算法。Redis在实现时,权衡了内存使用、性能开销、LFU的正确性,通过复用并拆分lru字段的方式,配合算法策略来实现近似的结果,虽然会有一定概率的偏差,但在内存数据库这种场景下,已经做得足够好了。
    20
    215
  • 甜宝仙女的专属饲养员
    又刷新了对lru和lfu的认知,这种突然打开知识盲区的天窗的感觉就如同一盆冷水,把我从地铁上这种迷迷糊糊的状态给满血复活
    2
    25
  • test
    1.选候选集:volatile前缀的是设置了过期时间的key,all前缀的是全部key; 2.算法:lru是最近最少使用,lfu是最近最不频繁使用,ttl是距离到期时间长短,ramdon是随机; 2.1 lru是自带了访问时间 2.2 lfu是带了访问次数,但是因为只有八位保存所以不是每访问一次就+1,而是每次原来访问次数乘以lfu_log_factor,加一再倒数,看是否大于随机值,大于则+1:double r = (double)rand()/RAND_MAX;double p = 1.0/(baseval*server.lfu_log_factor+1);if (r < p) counter++; 还有衰减机制,由lfu_decay_time控制,已过去n个lfu_decay_time,则将idle time加n。 3.淘汰规则:每次sample n个key,比如10个,放到pool里面,淘汰idle时间最长的key。再次淘汰的时候,继续抽样10个key,只把小于原pool中某个idle时间的key插入进去,即如果抽样出来的key比pool中所有key的idle时间都小,则不插入。然后淘汰pool中idle小的,保持pool在10个;
    14
  • xueyuan
    这篇文章就学到了很多,lfu的设计理念很有参考学习的意义。
    11
  • yeek
    偏极端情况下,数据短期内被高频访问,且计数器达到了很大值,且计数器的衰减设置的很大,导致衰减很慢,此时该数据就可能在缓存中长期驻留。 从长期来看,我觉得应该是避免频繁执行数据淘汰,否则会影响redis的效率,较好的做法应该是监控redis服务器的内存情况,以及相应的报警机制,定期统计redis中的key分布情况,交由使用方check数据合理性,以检验程序中对redis数据设置的过期时间,访问失效等是否合理。
    4
  • 写点啥呢
    关于计数衰减想请问老师,它发生的时机是在缓存被访问到还是Redis会定时刷新所有缓存计数进行衰减呢?对这两种衰减时机感觉都有不足,再次访问时候衰减能维持较低的性能损耗但是对于短期热点数据如果不会被访问那么计数就不准确还会导致污染问题。如果是全量定时刷新那么又会带来很多性能损耗。
    2
    3
  • escray
    有缓存过期时间和缓存淘汰机制,为什么还会出现缓存污染? 这一讲算是补上了之前留下来的一个坑——前面讲过了 LRU 算法,但是对于 LFU 一直留到这里才讲。我之前望文生义的以为 LFU,就是按照访问频次来淘汰,但是没有考虑到如果次数相同,那么还是要看访问时间;另外就是巧妙的拆分了 RedisObject 里面的 lru 字段,用 ldt 和 counter 来实现算法。 能看懂计数器规则的公式,但是不理解为什么要这么计算。还有那个 衰减因子配置项 lfu_decay_time 的相关计算也比较有意思,但是不知所以然,此处必有蹊跷。 之前看 LRU 和 LFU 比较多,忽略了 volatile-ttl 策略,这次正好补上了。 使用了 LFU 策略之后,应该还是会有缓存污染的情况,但是被污染的比例,或者说造成的影响应该小很多。假设 Redis 每次收到的请求都是全量扫描或接近于,那么 LFU 是不是就会失效,或者说缓存污染就会比较严重?
    2
  • bigben
    未达到触发淘汰机制的阈值之前,会被污染的;淘汰时也不是所有被污染key被淘汰,所以也还是被污染的;
    1
  • 而立斋
    这才是美妙的设计!!!那个随机数的作用也是神奇,能够有限的减缓计数器增长的速度,而且是数越大,越稳定
    1
  • zenk
    缓存污染还有一个实时性问题吧 越小的时间范围内准确识别的难度越大,有时业务方都无法确保数据的时效性,更别说缺少业务信息的Redis 所以,不管什么策略,都无法避免绝对的没有污染
    1
收起评论
显示
设置
留言
40
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部