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

C++实现简单的LRU-K算法 _ 解决偶发性访问热点问题【源码】

为什么 std::list 不适合 LRU-K 的第 K 次访问时间维护

LRU-K 的核心要求,是对每个 key 维护最近 K 次访问的精确时间戳。淘汰的时候,它看的不是最新那次访问,而是倒数第 K 次——也就是“第 K 次访问时间”。而 std::list 呢?它只擅长 O(1) 地把节点挪到头尾,却没法 O(1) 地定位并修改中间某次访问记录。

常见错误有哪些?

用环形数组 + 单调 tick 实现第 K 次访问时间推导

核心思路就一条:别实时排序。每个 key 只存一个 std::array 和一个游标 size_t cursor。新访问进来,覆盖掉最老的那次记录。第 K 次访问时间,就是 access_ticks[(cursor - K + 1) % K]。注意负数取模在 C++ 里是未定义行为,所以计算时一定先加上 K。

实操建议:

淘汰时不扫全量,改用热度桶分层采样

实时维护一个全局有序队列,代价太高,不值得。正确的做法是:等到需要驱逐时,才对候选 key 集合批量计算 access_ticks[(cursor - K + 1) % K],然后映射到离散热度桶。桶的划分可以参考 0–50ms、50–200ms、200–1s、>1s 这样的区间。

关键细节:

说实话,写对逻辑本身并不难。真正棘手的地方,在于控制 tick 更新和桶重组的时机——它们必须和缓冲池的 page pin/unpin、脏页刷盘节奏对齐。否则就会出现“刚标记为冷数据,下一秒就被事务强制 pin 住”的竞态问题。这一层耦合,在很多开源实现里都被忽略了。

本文转载于:https://www.php.cn/faq/2340847.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。