后端工程师的高阶面经
邓明
前 Shopee 高级工程师,Beego PMC
6888 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 50 讲
后端工程师的高阶面经
15
15
1.0x
00:00/00:00
登录|注册

32|缓存淘汰策略:怎么淘汰缓存命中率才不会下降?

低热度优先
先淘汰小对象
先淘汰大对象
变种:统计一段时间内的访问次数
实现复杂度高
根据使用次数淘汰对象
最不经常使用算法
变种:只在写操作时移动键值对
适用于时间局部性突出的应用
实现简单
最近最少使用算法
并发问题与使用lua脚本解决
直接控制某个业务的内存使用量
根据业务重要性设计淘汰策略
优先淘汰代价低的数据
避免使用Redis不当引起的线上故障
解决缓存占用内存过大的线上故障
了解本地缓存的内存控制和淘汰策略
了解公司的淘汰策略和调整情况
间接控制业务在Redis上的内存使用量
控制整个Redis实例的内存使用量
maxmemory和maxmemory_policy选项
LFU
LRU
腾出空间存放新数据
控制缓存的内存开销
思考题
优化缓存淘汰策略
面试准备
Redis支持的淘汰算法
淘汰算法
为什么要淘汰?
缓存淘汰策略

该思维导图由 AI 生成,仅供参考

你好,我是大明。今天我们来聊一个使用缓存的时候绕不开的话题——如何淘汰键值对?
这个问题在面试中也很常见。大多数人都能把八股文背好,也就是常见的 LRU 之类的策略都能回答出来。而它在面试中的独特优势,就是能够根据业务设计出花样繁多的解决方案。如果你能在面试中用上这些方案,就能给面试官留下很深刻的印象。
那么我们先从“为什么要淘汰”这个问题开始学习。

为什么要淘汰?

我们日常在使用缓存的时候,都会尝试控制整个缓存的开销,尤其是本地缓存的内存开销。比如说线上偶尔会遇到本地缓存了太多数据,导致应用内存不足的问题。如果是 Java 这种垃圾回收的语言,那么你就会遇到频繁地垃圾回收甚至 full GC 之类的问题。
所以用缓存肯定要控制住缓存的内存使用量。而这就会引出一个问题,万一我达到了内存使用上限,但是我又需要加入新的键值对,怎么办?最保守的做法就是直接报错,那么你就没有办法缓存新的数据了。后续如果缓存中已有的数据过期了,你就能缓存新的数据了。
但是大多数的业务是不能接受这种方案的,因为这一类的业务认为已经在缓存中的数据可能用不上了,虽然还没有过期,但是还是可以考虑淘汰掉,腾出空间来存放新的数据。这些新的数据比老的数据有更大的可能性被使用。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入探讨了缓存淘汰策略的重要性以及相关算法,特别是LRU和LFU两种最常见的淘汰算法。文章还提到了在面试准备中需要了解的问题和建议,以及如何通过实践来加深对缓存淘汰策略的理解。此外,还介绍了针对业务特性设计淘汰策略的亮点方案,包括按照优先级淘汰、先淘汰大对象或小对象、以及低热度优先等策略。总的来说,本文内容涵盖了缓存淘汰策略的基本概念和实际应用,对于需要了解缓存淘汰策略的读者来说,是一篇值得阅读的文章。文章还提出了一个针对业务特性来设计的按照优先级淘汰的算法,根据怎么计算优先级又可以进一步细分成大对象先淘汰、小对象先淘汰、根据热度来淘汰。这些方案在 Redis 上落地的时候,都需要借助 Redis 的有序集合,而且为了避免并发问题,你操作 Redis 的时候都是要通过 lua 脚本封装一系列操作的。文章还提出了两个思考题,引发读者思考。整体而言,本文内容涵盖了缓存淘汰策略的基本概念和实际应用,对于需要了解缓存淘汰策略的读者来说,是一篇值得阅读的文章。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《后端工程师的高阶面经》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(7)

  • 最新
  • 精选
  • Geek_2c128e
    最后那个亮点方案中,新增的那个有序集合,这不是又加大了内存占用吗?????

    作者回复: 这是必然的代价。不过这里只存了 key,所以也没那么严重。毕竟值占据的内存比 key 的多。

    2023-09-02归属地:北京
    2
    2
  • 文敦复
    问题1,直接控制某个业务的内存使用量:可以proxy客户端redis指令,然后判定每次发送的对象的大小。但是问题又来了,java不能很好的判定当前对象的大小吧,可以通过传输的字节大小累加??还有就是对象过期是在redis上,proxy如果要精准控制,也要自己做过期处理或者监听redis的过期事件?感觉得不偿失,还不如每个应用1个redis实例来的直观?

    作者回复: 1. 不能……有一种粗暴的方式就是要求客户端只能存储 byte,然后就比较容易计算了。 2. 对的,你的顾虑很有道理,大规模监听 redis 的过期事件确实不怎么靠谱。但是怎么说呢,就是这个面试意义大于实践意义,你不到逼不得已不要搞这种骚操作……我搞过一次就不想再搞第二次。

    2023-10-10归属地:四川
    1
  • sheep
    问题2:“它会先检测有序集合里面的元素个数有没有超过允许的键值对数量上限,如果没有超过,就写入键值对”,在没用lua时,可能有两个操作同时判断元素个数没用超过允许的键值对数量上限,然后同时进行写入了键值对

    作者回复: 对的,并发问题。

    2024-01-20归属地:广东
  • Lum
    老师会不会出一期,如何设计缓存结构,来说明一下各个结构的内存占用情况,并且在什么情况用什么样的数据结构比较好的

    作者回复: 暂时没有这个计划。一般来说,选择数据结构应该是先看业务场景吧?比如说很多场景要求用 zset 之类的,想换也换不了。 不过如果是站在面试的角度话,如果你想刷优化 Redis 内存使用量的,确实是可以考虑使用更加紧凑的内存结构,比如说 intset 之类的,不过都是首先得业务允许。

    2023-10-27归属地:北京
  • Geek_aecbf4
    问题2:极端情况会引起oom, 当第一个请求完成有序集合的删除操作,此时第二个请求过来会判断未超限,导致2个请求都会去set

    作者回复: 赞!

    2023-09-26归属地:北京
    2
  • peter
    本地缓存最常用的有哪些? 在生产实践中,网络公司的网站是大量采用本地缓存还是很少使用本地缓存?

    作者回复: 只有性能要求很高的时候才会用,因为本地缓存一致性问题更加严重。

    2023-09-01归属地:北京
    3
  • shikamaru
    LRU(Least Recently Used)翻译为最近最少使用,就是以讹传讹,least是修饰recently的,根本没有最少的意思,意为“最不近”,翻译为“最久未用”比较合理
    2024-03-14归属地:四川
收起评论
显示
设置
留言
7
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部