用冰箱讲透缓存策略:什么是 LRU、LFU、TinyLFU、W-TinyLFU

121 阅读3分钟

本文来自 mp.weixin.qq.com/s/IFNAOzuPm…

1、LRU(Least Recently Used,最近最少使用)

思想:

淘汰最近最少被访问的元素。

类比:

你有一个冰箱放饮料,容量是 5 瓶。你每天可能会喝其中一些,如果冰箱满了,需要放新饮料时,就把最久没喝的那一瓶扔掉。

举例:

冰箱里有:可乐、雪碧、果汁、牛奶、咖啡。

  • 你连续几天喝的是可乐、雪碧、果汁;
  • 要放进新饮料“酸奶”时发现冰箱满了;
  • 检查哪些最久没喝,发现咖啡最久没人动,就把咖啡扔掉。

适用场景:

数据有时间局部性,即最近用过的数据很可能还会被用到。


2、LFU(Least Frequently Used,最不常用)

思想:

淘汰被使用次数最少的元素。

类比:

冰箱每瓶饮料都记录过去一个月你喝了多少次,谁喝得最少,就优先被淘汰。

举例:

  • 可乐喝了 10 次,雪碧 8 次,牛奶 1 次;
  • 新饮料来了,要放进冰箱,淘汰喝得最少的牛奶。

问题:

即使牛奶最近没人喝,但因为历史上喝过几次,仍然可能保留;
而一些最近才开始变得受欢迎的饮料,可能反而被淘汰。


3、TinyLFU(轻量级 LFU)

思想:

在 LFU 的基础上,只记录近期访问频率,而且用非常节省空间的数据结构记录(如 Count-Min Sketch)。

类比:

你不可能详细记录每瓶饮料的历史喝了多少次,于是你只记录最近几天喝饮料的次数,用一个模糊但省空间的方式。

  • 每次放新饮料前,先查它最近有没有被喝过;
  • 如果频率很低,那就拒绝加入冰箱;
  • 如果频率高,再考虑淘汰掉频率低的现有饮料。

特点:

  • 占用内存少;
  • 判断是否“值得”缓存,而不是盲目地加入缓存;
  • 适合数据流量大、热点变化快的场景。

4、W-TinyLFU(Window-TinyLFU)

思想:

在 TinyLFU 基础上,引入一个窗口区(Window Cache) ,让新来的数据有机会“试用”,再决定是否放入正式缓存。

类比:

你在冰箱旁边放一个试饮格子,所有新饮料都会先放在试饮区:

  • 如果在试饮期间被喝了,那说明这饮料可能会受欢迎,就放入正式冰箱;
  • 如果没人喝,那说明没价值,直接扔掉;
  • 正式冰箱还是用 TinyLFU 的频率机制来决定淘汰谁。

举例:

  • 新饮料“椰子汁”先放入试饮区;
  • 如果有人来喝它一次,就升到主冰箱中;
  • 如果没人动它,它会被新来的饮料挤出去;
  • 主冰箱内谁频率最低就被淘汰。

好处:

解决了 TinyLFU 不太友好对待“新元素”的问题;
兼顾频率与新鲜度,效果更全面。


对比

策略原理优点缺点
LRU淘汰最近最少访问的元素简单高效,适合时间局部性无法识别高频但间隔长的访问
LFU淘汰使用频率最低的元素能保留常用数据不适合频率变化快的数据
TinyLFU用精简结构统计近期频率空间省,命中率高新数据可能没有加入的机会
W-TinyLFU试用区 + TinyLFU兼顾新旧数据,命中率更优实现更复杂,需要参数调优