### 课堂目标 1. 理解redis的淘汰策略 2. 如何进行配置 # 一、什么是Redis淘汰策略 如果没有淘汰策略,redis的key就会用不过期,有可能导致redis就会导致oom。 当 Redis 所使用的内存达到 配置的阈值时,Redis 会根据设定的淘汰策略来删除一些键,以便为新数据腾出空间。 ### 核心配置 首先,你需要在 \*\*redis.conf\*\* 文件中或在运行时使用 \*\*CONFIG SET\*\* 命令设置两个关键参数: 1. \*\*\`maxmemory\`\*\*: 指定 Redis 可以使用的最大内存量(例如 maxmemory 2gb)。当内存使用达到这个值,触发淘汰机制。 2. \*\*\`maxmemory-policy\`\*\*: 指定当内存达到上限时,使用哪种淘汰策略。 ------ ### 八大淘汰策略 Redis 提供了 8 种主要的淘汰策略,可以分为几类: 两大类 0不淘汰 - 没有配置过期时间的Key 1、按时间最近使用的 2、按访问次数最少 3、随机淘汰 - 有配置过,过期时间的Key 4、按时间最近使用的 5、按访问次数最少 6、随机淘汰 7、最短TTL淘汰 #### A. 不淘汰,直接返回错误 1. \*\*\`noeviction\`\*\* (\*\*默认策略\*\*) - \*\*行为\*\*:当内存不足时,所有会申请更多内存的\*\*写入命令\*\*(如 \`SET\`, \`LPUSH\`, \`HINCRBY\` 等)都会返回错误。\*\*读取命令\*\*(如 \`GET\`, \`LRANGE\` 等)仍然可以正常执行。 - \*\*使用场景\*\*:如果你把 Redis 用作\*\*数据库\*\*而非\*\*缓存\*\*,并且希望确保数据永远不会被意外删除,可以使用此策略。你需要通过其他方式(如扩容)来处理内存不足的问题。 #### B. 在所有键中淘汰(无论是否设置过期时间) 这类策略会从整个数据集的键中(包括没有设置过期时间的键)进行筛选和淘汰。 !\[image-20251119151317260\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251210092625840.png) 1. \*\*\`allkeys-lru\`\*\* (\*\*最常用策略之一\*\*) LRU (Least Recently Used) 最近(时间)最少使用 - \*\*行为\*\*:从\*\*所有键\*\*中,使用 \*\*LRU 算法\*\*(Least Recently Used) 淘汰\*\*最近最少使用\*\*的键。(时间) - \*\*使用场景\*\*:适用于某些键在短时间内被频繁访问,但之后长时间不再使用的场景 2. \*\*\`allkeys-lfu\`\*\* (Redis 4.0+) LFU (Least Frequently Used) 最不经常使用(次数) - \*\*行为\*\*:从\*\*所有键\*\*中,使用 \*\*LFU 算法\*\* (Least Frequently Used)淘汰\*\*最不经常使用\*\*的键(次数)。LFU 统计的是访问频率 - \*\*使用场景\*\*:如果你的应用中有明显的"热点数据"(即一部分数据被频繁访问),同时希望将 Redis 用作\*\*缓存\*\*,这是非常理想的选择。它可以自动将不常用的数据清理掉。 \`\`\` LRU:相信"最近访问的还会再访问",所以会删除长时间没有访问的 LFU:相信"经常访问的还会再访问",所以会删除次数最少的 \`\`\` 3. \*\*\`allkeys-random\`\*\* - \*\*行为\*\*:从\*\*所有键\*\*中,\*\*随机\*\*选择一个键进行淘汰。 - \*\*使用场景\*\*:当所有键被访问的概率都差不多时,可以用这个策略。它的速度很快,但淘汰的键可能很重要,也可能不重要,比较"随意"。 #### C. 仅在设置了过期时间的键中淘汰 这类策略只会在那些通过 \`EXPIRE\` 等命令设置了 \*\*TTL\*\* 的键中进行筛选和淘汰。\*\*没有设置过期时间的键是安全的,不会被淘汰。\*\* 1. \*\*\`volatile-lru\`\*\* - \*\*行为\*\*:从\*\*设置了过期时间的键\*\*中,使用 \*\*LRU 算法\*\* 淘汰。 - \*\*使用场景\*\*:当你希望某些核心键(未设置 TTL)永久保存,而只愿意牺牲缓存数据(设置了 TTL)时使用。 2. \*\*\`volatile-lfu\`\*\* (Redis 4.0+) - \*\*行为\*\*:从\*\*设置了过期时间的键\*\*中,使用 \*\*LFU 算法\*\* 淘汰。 - \*\*使用场景\*\*:与 \`volatile-lru\` 类似,但希望根据频率而非最近使用时间来做更精细的淘汰。 3. \*\*\`volatile-random\`\*\* - \*\*行为\*\*:从\*\*设置了过期时间的键\*\*中,\*\*随机\*\*选择一个键进行淘汰。 - \*\*使用场景\*\*:当你只想在缓存数据中随机淘汰时使用。 4. \*\*\`volatile-ttl\`\*\* - \*\*行为\*\*:从\*\*设置了过期时间的键\*\*中,淘汰 \*\*TTL 剩余时间最短\*\*的键,即最快将要过期的键。 - \*\*使用场景\*\*:这是一种"提前清理"策略,希望尽快释放那些马上就要过期的键所占用的内存。 ------ ### 策略选择总结与建议 \| 策略 \| 淘汰范围 \| 算法 \| 适用场景 \| \| :-------------------- \| :----------------- \| :----------------- \| :------------------------------------------------- \| \| \*\*noeviction\*\* \| - \| 不淘汰 \| \*\*数据库模式\*\*,数据不能丢,写入报错由应用处理。 \| \| \*\*allkeys-lru\*\* \| \*\*所有键\*\* \| LRU (最近最少使用) \| \*\*通用缓存模式\*\*,存在热点数据。\*\*最推荐\*\*。 \| \| \*\*\`allkeys-lfu\`\*\* \| \*\*所有键\*\* \| LFU (最不经常使用) \| \*\*缓存模式\*\*,希望根据访问频率淘汰(Redis 4.0+)。 \| \| \*\*\`allkeys-random\`\*\* \| \*\*所有键\*\* \| 随机 \| 所有键访问概率相近,追求速度。 \| \| \*\*\`volatile-lru\`\*\* \| \*\*有过期时间的键\*\* \| LRU \| 需区分核心数据与缓存数据,只淘汰缓存。 \| \| \*\*\`volatile-lfu\`\*\* \| \*\*有过期时间的键\*\* \| LFU \| 同上,但使用频率淘汰(Redis 4.0+)。 \| \| \*\*\`volatile-random\`\*\* \| \*\*有过期时间的键\*\* \| 随机 \| 只在缓存中随机淘汰。 \| \| \*\*\`volatile-ttl\`\*\* \| \*\*有过期时间的键\*\* \| TTL (剩余时间) \| 希望尽快释放即将过期的内存。 \| !\[image-20251119142730492\](https://woniumd.oss-cn-hangzhou.aliyuncs.com/daiwei/java/20251119142737589.png) ### 配置方法 \*\*1. 修改配置文件 (\`redis.conf\`):\*\* \`\`\` # 设置最大内存为 1GB maxmemory 1gb # 设置淘汰策略为 allkeys-lru maxmemory-policy allkeys-lru \`\`\` \*\*2. 运行时动态配置 (无需重启):\*\* bash \`\`\` # 连接 Redis 后执行 CONFIG SET maxmemory 2gb CONFIG SET maxmemory-policy volatile-lru \`\`\` ### 重要补充:近似算法 需要注意的是,Redis 使用的 LRU 和 LFU 并非绝对精确的实现,而是一种\*\*近似算法\*\*。为了节省内存和提高性能,Redis 并不会为每个键维护一个精确的访问时间戳或完整的访问频率计数器,而是通过采样一小部分键,然后从中淘汰最符合条件的那个。 这意味着它可能不会淘汰掉"最完美"的那个键,但会在性能和效果之间取得一个非常好的平衡,其结果是\*\*几乎正确\*\*的,对绝大多数应用来说已经足够。
13-3阶内容-1.7-redis key淘汰策略
https://xiaochenblog.icu/archives/ea60e176-eea8-4803-952a-631749a94330
评论