设计一个key历史上被访问100次但最近没碰、另有2000个key各只访问1次但更新的场景,对照LRU和LFU两种策略给出的完全相反的淘汰结果。
一个key历史上很火但最近没人碰,另一批key只访问过一次但都是刚刚发生的。
操作SET star_key,GET它100次(历史上非常火) 再SET 2000个filler_key,每个只GET 1次(但发生在star_key之后,是"最近"的访问)
同样的访问模式,先用allkeys-lru跑一遍。
结果LRU策略下 star_key 是否还在: 0(不在了!) DBSIZE: 713 evicted_keys: 2042
结果:哪怕star_key历史上被访问过100次,LRU只看"最后一次访问是什么时候"——它最后一次被访问,是在2000个filler_key开始被访问之前,所以在LRU眼里,它是"最久没被碰过"的那一批,被淘汰了。
完全相同的访问顺序和次数,只换策略。
结果LFU策略下 star_key 是否还在: 1(活下来了!) DBSIZE: 713 evicted_keys: 3330 star_key的FREQ: 11
结果完全反过来了:LFU看的是"历史上一共被访问了多少次",star_key的100次历史访问转化成了一个较高的FREQ计数(11,同样是对数压缩后的值),哪怕它已经很久没被访问,这个累积的频率优势足够让它在淘汰竞争中活下来——filler_key们虽然"新",但每个都只被访问过1次,频率计数远低于star_key。
每一步都是本文上面用redis-cli和redis-py跑出来的原始结果。
allkeys-lru vs allkeys-lfu:用同一份访问模式对照两种策略