dot Redis 8 已发布——它是开源的

了解更多

每个 Redis 开发者都应该知道的缓存逐出策略

这是一个真实世界的场景。你设置了一个 Redis 数据库,它在加速你的应用方面发挥了巨大作用。但是随着数据涌入和数据量的增加,你注意到一个潜在的问题:缓存正在填满。当缓存满了会发生什么?你可能听说过缓存逐出,但也许你对细节不太清楚。 

你不是一个人。无论你是初创公司的开发者还是大型企业的系统管理员,理解缓存逐出以及了解何时何地实现它都非常重要。在本指南中,我们将探讨原因。

理解缓存逐出

当你使用 Redis(或任何依赖缓存的系统……但我们在这里仅凭自己的专业知识发言)时,缓存逐出策略是缓存管理的一个关键方面。它解决了缓存大小和内存使用的问题。当缓存达到其限制时,它必须做出一个关键决定:是应该拒绝新数据,还是应该通过丢弃旧数据来腾出空间?

这就是缓存逐出发挥作用的地方。无论你如何解决,缓存逐出都涉及在缓存填满时确定要保留哪些缓存条目以及要丢弃哪些。这对于实现或维持最佳的应用性能和一致性至关重要。

在缓存的上下文中,逐出(Eviction)不涉及任何房东或逾期租金。相反,它指的是从缓存中删除特定数据的过程。因为当缓存达到其最大存储容量时,必须删除一些数据以为新数据腾出空间——就像一个书架,你无法强行把另一本书塞进现有空间一样。

缓存逐出策略

缓存逐出策略是规定系统在缓存满时如何响应的协议。关于逐出(即删除)哪些数据的决定是根据几种策略之一以编程方式做出的。常见的策略包括

  • 最近最少使用 (LRU):想象一下:你正在整理衣橱。你会先扔掉什么?那件你自 80 年代以来就没穿过的时髦衬衫,对吧?或者那件十年了却小了两个尺码的连衣裙,你一直告诉自己有一天会重新穿上它?类似地,LRU 缓存逐出策略首先逐出最近最少访问的缓存条目,其假设是最近没有访问过的条目在短期内不太可能被需要。
  • 最不常用 (LFU):现在,想象你是一位图书管理员。你会移除哪些书籍来腾出图书馆书架上的空间?很可能是那些借阅次数最少的书。这就是 LFU 的工作原理。LFU 缓存逐出策略首先逐出访问频率最低的缓存条目,假设不经常访问的条目在不久的将来不太可能被需要。
  • Window TinyLFU (W-TinyLFU):这个有点复杂。想象你是一个广播电台 DJ。你想播放那些既受欢迎(经常被点播)又时兴(最近的热门歌曲)的歌曲。W-TinyLFU 通过同时考虑数据的访问时间和访问频率来保留缓存中最相关的条目。这种缓存逐出策略在访问模式多变和分布式缓存环境中尤其有益。
  • 存活时间 (TTL):考虑一盒新鲜的浆果。即使你每天都吃,总有一天它们在冰箱里放得太久,开始发霉。这时候就该把它们扔掉了,不管你多喜欢它们。TTL 在缓存中是一个类似的概念。每个缓存条目都被标记了一个特定的“过期日期”。一旦达到时间限制,该条目就会被逐出,无论它被访问的频率或时间有多近。这种方法确保数据不会停留过久,尤其是在数据有可能过时或不再相关的情况下。在数据定期更新且需要确保缓存不提供陈旧信息的场景中,这是一种首选策略。

这些策略的有效性取决于具体的用例。

默认设置的风险

虽然 Redis 确实有一个默认的逐出策略 (volatile-LRU),但完全依赖它而不理解其含义可能会有风险。应用服务于不同的用户需求,这意味着数据模式和逐出要求可能差异很大。设置正确的逐出策略可以避免潜在的麻烦。

监控:第一道防线

在考虑逐出之前,了解何时采取行动至关重要。这就是监控工具发挥作用的地方。

Redis 提供了像 INFO 命令这样的工具来监控缓存性能,而 New Relic 和 Datadog 等第三方监控工具则提供更详细的分析。 

调优缓存性能涉及根据从监控性能中发现的信息调整缓存设置和逐出策略。在分布式缓存场景中,监控和调优变得更加关键,以确保跨多个节点的缓存管理一致且高效。(我们提供了关于如何选择第三方监控工具的额外建议。)

在 Redis 中选择正确的逐出策略

在 Redis 中,缓存条目的数据结构由 maxmemory 配置指令管理,该指令设置内存限制。maxmemory-policy 配置指令指导 Redis 根据所选的缓存逐出策略做出逐出决定。maxmemory-policy 和逐出策略都属于存储在 redis.conf 配置文件中的配置设置。

Redis 有相当多的逐出策略,但你可能最关心这些。

allkeys-lru 

移除最近最少使用的缓存条目,无论它们是否设置了过期时间。

  • Redis 跟踪每个键上次访问的时间。每次读取或写入键时,Redis 都会更新此信息。
  • 当达到内存限制且 Redis 需要逐出键时,它会查找最长时间未被访问的键。这些就是“最近最少使用”的键。
  • Redis 逐出这些键以为新数据腾出空间。
  • allkeys-lru 策略适用于 Redis 数据库中的所有键,无论它们是否设置了过期时间。这与 volatile-lru 策略形成对比,后者仅适用于设置了过期时间的键。

volatile-lru

移除设置了过期时间的最近最少使用的缓存条目。这适用于需要定期刷新数据的场景。

allkeys-lfu 

当 Redis 需要为新数据腾出空间时,此策略会移除最不常用的键。

  • Redis 跟踪每个键的访问频率。每次读取或写入键时,Redis 都会增加与该键关联的计数器。
  • 当达到内存限制时,Redis 会查找计数器值最低的键,这些键被视为“最不常用”的键。
  • Redis 逐出这些键以为新数据腾出空间。

volatile-lfu

与 allkeys-lfu 类似,此策略仅适用于设置了过期时间的键。

volatile-ttl

此策略首先移除 TTL 最短的键。

  • Redis 跟踪每个键的 TTL。TTL 是一个持续时间,在此持续时间后,键会自动删除。
  • 当达到内存限制时,它会查找 TTL 最短的键。这些是即将到期的键。
  • Redis 逐出这些键以为新数据腾出空间。

noeviction

此策略在达到内存限制并收到写命令时,不会逐出任何键,而是返回一个错误。(不要扔掉衣橱里的任何东西。发送警报!)

  • 当达到内存限制并收到写命令时,Redis 会检查逐出策略。
  • 如果策略设置为 noeviction,Redis 不会逐出任何键。相反,它会向写命令返回一个错误。
  • 应用程序代码必须决定如何处理该错误情况。

每种策略都有其优点和缺点。最适合你的策略取决于你的具体需求。

拥有一个结构良好的缓存,并结合正确的缓存逐出策略,对于在处理海量数据时实现性能目标至关重要。Redis 凭借其多功能的强大能力,是一个出色的缓存解决方案,也是处理大型数据集的应用的强大资产。有效的缓存管理不仅通过缓存命中加速数据检索,还减轻了缓存未命中的影响,使 Redis 成为适用于各种用例的可靠高效的缓存解决方案。

通过我们的综合指南探索规模化缓存的复杂性:使用 Redis 实现规模化缓存的权威指南。在这份一站式资源中,学习从缓存基础知识到高级企业应用技术。