发布于2026-07-18 阅读(0)
扫一扫,手机访问
咱们先直说了吧:std::list + std::unordered_map 这套组合拳,打不了 LRU-K。哪怕 K 只取 2,只要你还想着遍历链表去更新访问记录,那缓存驱逐的延迟就会随着访问频率一路走高,最后彻底崩盘。

LRU-K 的核心要求,是对每个 key 维护最近 K 次访问的精确时间戳。淘汰的时候,它看的不是最新那次访问,而是倒数第 K 次——也就是“第 K 次访问时间”。而 std::list 呢?它只擅长 O(1) 地把节点挪到头尾,却没法 O(1) 地定位并修改中间某次访问记录。
常见错误有哪些?
核心思路就一条:别实时排序。每个 key 只存一个 std::array 和一个游标 size_t cursor。新访问进来,覆盖掉最老的那次记录。第 K 次访问时间,就是 access_ticks[(cursor - K + 1) % K]。注意负数取模在 C++ 里是未定义行为,所以计算时一定先加上 K。
实操建议:
uint64_t,别依赖系统时间。系统时间可能回拨,精度也没保障。size_t,取模时写成 (cursor + K - 1) % K,别直接 cursor - K + 1 取模。实时维护一个全局有序队列,代价太高,不值得。正确的做法是:等到需要驱逐时,才对候选 key 集合批量计算 access_ticks[(cursor - K + 1) % K],然后映射到离散热度桶。桶的划分可以参考 0–50ms、50–200ms、200–1s、>1s 这样的区间。
关键细节:
std::vector> 实现,每个桶内的 key 按插入顺序排列,不排序。now_tick - access_time > 1s 的 key 移到新桶,防止冷数据永久滞留。说实话,写对逻辑本身并不难。真正棘手的地方,在于控制 tick 更新和桶重组的时机——它们必须和缓冲池的 page pin/unpin、脏页刷盘节奏对齐。否则就会出现“刚标记为冷数据,下一秒就被事务强制 pin 住”的竞态问题。这一层耦合,在很多开源实现里都被忽略了。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8