dot 快速的未来即将在您所在的城市举办的活动中到来。

加入我们在 Redis 发布会

每个 Redis 开发人员都应该知道的缓存驱逐策略

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

您并不孤单。无论您是初创公司的开发人员还是大型企业的系统管理员,了解缓存驱逐以及何时以及如何实施它都很重要。在本指南中,我们将探讨原因。

了解缓存驱逐

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

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

在缓存的上下文中,驱逐不涉及任何房东或逾期租金。相反,它指的是从缓存中删除特定数据的过程。因为当缓存达到其最大存储容量时,必须删除一些数据以腾出空间用于新数据——就像书架一样,您不能强迫另一本书进入可用的空间。

缓存驱逐策略

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

  • **最近最少使用** (LRU):想象一下:您正在清理衣柜。您先扔掉什么?那件您从 80 年代开始就再也没有穿过的怪异衬衫,对吧?或者那件您承诺自己将来会再次穿上的、已经过时了十年且小了两个尺码的连衣裙?类似地,LRU 缓存驱逐策略根据最近访问的项目不太可能很快被需要这一假设,首先驱逐最不常访问的缓存条目。
  • **最不常使用** (LFU):现在,想象一下您是一位图书管理员。您会删除哪些书以在图书馆书架上腾出空间?可能是那些最不常借阅的书。这就是 LFU 所做的。LFU 缓存驱逐策略首先驱逐最不常访问的缓存条目,假设不常访问的条目不太可能在不久的将来被需要。
  • **窗口 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 策略仅适用于设置了过期时间的键。

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 规模化缓存的终极指南。本资源涵盖了从缓存基础到高级企业应用程序技术,是您的一站式资料库。