<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>淘汰策略 on giftiaのblog</title><link>https://hch1212.github.io/tags/%E6%B7%98%E6%B1%B0%E7%AD%96%E7%95%A5/</link><description>Recent content in 淘汰策略 on giftiaのblog</description><generator>Hugo</generator><language>zh-CN</language><lastBuildDate>Wed, 15 Jul 2026 17:23:30 +0800</lastBuildDate><atom:link href="https://hch1212.github.io/tags/%E6%B7%98%E6%B1%B0%E7%AD%96%E7%95%A5/index.xml" rel="self" type="application/rss+xml"/><item><title>W-TinyLFU：Caffeine 的高命中率缓存淘汰算法</title><link>https://hch1212.github.io/posts/2026/07/w-tinylfucaffeine-%E7%9A%84%E9%AB%98%E5%91%BD%E4%B8%AD%E7%8E%87%E7%BC%93%E5%AD%98%E6%B7%98%E6%B1%B0%E7%AE%97%E6%B3%95/</link><pubDate>Tue, 14 Jul 2026 00:00:00 +0000</pubDate><guid>https://hch1212.github.io/posts/2026/07/w-tinylfucaffeine-%E7%9A%84%E9%AB%98%E5%91%BD%E4%B8%AD%E7%8E%87%E7%BC%93%E5%AD%98%E6%B7%98%E6%B1%B0%E7%AE%97%E6%B3%95/</guid><description>&lt;h2 id="背景"&gt;背景&lt;/h2&gt;
&lt;p&gt;缓存淘汰算法决定&lt;strong&gt;当缓存满时该踢谁&lt;/strong&gt;。一个理想的淘汰算法需要同时满足：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;高命中率&lt;/strong&gt;：尽量保留未来会被访问的数据&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;低内存开销&lt;/strong&gt;：淘汰算法自身的元数据不能太占内存&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;时间/空间适应性&lt;/strong&gt;：能应对访问模式随时间变化&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="lfuleast-frequently-used"&gt;LFU（Least Frequently Used）&lt;/h2&gt;
&lt;p&gt;记录每个元素的访问频率，淘汰频率最低的。&lt;/p&gt;
&lt;p&gt;优点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;对热点数据友好：高频数据不容易被淘汰&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;缺点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;新元素冷启动&lt;/strong&gt;：刚加入的元素频率很低，还没积累就被踢了&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;历史包袱&lt;/strong&gt;：曾经高频但现在已经冷的数据占据缓存，很难被淘汰&lt;/li&gt;
&lt;li&gt;频率计数器占用内存大（每个 key 都要记录精确计数）&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="lruleast-recently-used"&gt;LRU（Least Recently Used）&lt;/h2&gt;
&lt;p&gt;按最近访问时间排序，淘汰最久没访问的。&lt;/p&gt;
&lt;p&gt;优点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;实现简单（双向链表 + 哈希表）&lt;/li&gt;
&lt;li&gt;对突发流量友好&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;缺点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;扫描污染&lt;/strong&gt;：一次全表扫描会把整个缓存洗成新数据，真正热数据被挤出&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;频率盲区&lt;/strong&gt;：只关心时间，不关心访问频率，一次访问和一百次访问在 LRU 里权重相同&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="slrusegmented-lru"&gt;SLRU（Segmented LRU）&lt;/h2&gt;
&lt;p&gt;将缓存分成两段：&lt;strong&gt;试用段（probation）&lt;/strong&gt; 和 &lt;strong&gt;保护段（protected）&lt;/strong&gt;。&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;新元素先进入试用段&lt;/li&gt;
&lt;li&gt;在试用段内被再次访问，晋升到保护段&lt;/li&gt;
&lt;li&gt;淘汰从试用段发生&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;优点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;用&amp;quot;二次机会&amp;quot;解决 LRU 的扫描污染问题&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;缺点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;依然是纯 LRU 思想，不感知频率——保护段满时元素降级回试用段而非直接淘汰，但一个被访过 100 次却在试用段的元素仍可能先被踢&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="countminsketch近似计数器"&gt;CountMinSketch（近似计数器）&lt;/h2&gt;
&lt;p&gt;精确记录每个 key 的访问频率代价太高。Count-Min Sketch 用&lt;strong&gt;概率换空间&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;维护一个 &lt;code&gt;d × w&lt;/code&gt; 的二维计数器矩阵&lt;/li&gt;
&lt;li&gt;每个元素经过 d 个哈希函数映射到每行的某个位置，计数器 +1&lt;/li&gt;
&lt;li&gt;查询时取 d 个位置的最小值作为估计频率&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;特点：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;只会&lt;strong&gt;高估&lt;/strong&gt;不会低估（保证 No False Negative）&lt;/li&gt;
&lt;li&gt;内存固定，与缓存元素数量无关&lt;/li&gt;
&lt;li&gt;支持周期性衰减（除以 2），让历史数据随时间自然消退&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="tinylfu"&gt;TinyLFU&lt;/h2&gt;
&lt;p&gt;TinyLFU 是 W-TinyLFU 的核心组件。它的思想：&lt;strong&gt;用一个轻量级频率估计器替代精确计数&lt;/strong&gt;。&lt;/p&gt;</description></item></channel></rss>