Redis【有与无】【UR5】将Redis用作LRU缓存

本文基于Redis 6.0.9版本,前提至少 Redis 3.0或更高版本。

目录

1.将Redis用作LRU缓存

1.1.Maxmemory配置指令

1.2.驱逐政策(Eviction policies)

1.3.驱逐过程如何进行

1.4.近似LRU算法

1.5.新的LFU模式


1.将Redis用作LRU缓存

当Redis用作缓存时,通常很方便在添加新数据时让它自动逐出旧数据。 此行为在开发人员社区中是众所周知的,因为它是流行的内存缓存系统的默认行为。

LRU实际上只是支持的驱逐方法之一。 此页面涵盖了Redis maxmemory指令的更一般主题,该指令用于将内存使用限制为固定量,并且还深入介绍了Redis使用的LRU算法,实际上是精确的LRU的近似值。

从Redis版本4.0开始,引入了新的LFU(Least Frequently Used)驱逐策略。 本文档的单独部分对此进行了介绍。

1.1.Maxmemory配置指令

使用maxmemory配置指令是为了将Redis配置为对数据集使用指定的内存量。 可以使用redis.conf文件设置配置指令,或者稍后在运行时使用CONFIG SET命令设置。

例如,为了配置100 MB的内存限制,可以在redis.conf文件中使用以下指令。

maxmemory 100mb

将maxmemory设置为零将导致没有内存限制。 这是64位系统的默认行为,而32位系统使用3GB的隐式内存限制。

当达到指定的内存量时,可以在称为策略的不同行为之间进行选择。 Redis可能只返回命令错误,从而导致使用更多的内存,或者它可以逐出某些旧数据,以便在每次添加新数据时返回指定的限制。

1.2.驱逐政策(Eviction policies)

使用maxmemory-policy配置指令配置达到最大内存限制时,会发生确切的行为Redis。

可以使用以下策略:

  • noeviction: 当达到内存限制并且客户端尝试执行可能导致使用更多内存的命令时返回错误(大多数写入命令,但是DEL和一些其他例外)。
  • allkeys-lru: 通过尝试先删除较新的(LRU)键来移出键,以便为添加的新数据腾出空间。
  • volatile-lru: 通过尝试先删除最近使用较少的(LRU)密钥来移出密钥,但仅在已设置过期的密钥中才能移出密钥,以便为添加的新数据腾出空间。
  • allkeys-random: 随机退出键,以便为添加的新数据腾出空间。
  • volatile-random: 为了为添加的新数据腾出空间,可随机逐出逐个按键,但仅逐个设置了到期时间的逐出按键即可。
  • volatile-ttl: 逐出具有过期设置的密钥,并尝试首先逐出具有较短生存时间(TTL)的密钥,以便为添加的新数据腾出空间。

如果没有用于退出与先决条件匹配的键,则volatile-lru,volatile-random和volatile-ttl策略的行为类似于noeviction。

选择正确的逐出策略很重要,具体取决于应用程序的访问模式,但是您可以在应用程序运行时在运行时重新配置该策略,并使用Redis INFO输出监视缓存未命中和命中的次数,以调整设置。

一般而言,根据经验:

  • 当您期望请求的受欢迎程度呈幂律分布时,请使用allkeys-lru策略,也就是说,您希望访问元素的子集比访问其他元素更多。 如果不确定,这是一个不错的选择。
  • 如果您具有对所有键进行连续扫描的周期性访问,或者当您期望分布是统一的(所有元素以相同的概率被访问)时,请使用allkeys-random。
  • 如果您希望能够在创建缓存对象时通过使用不同的TTL值向Redis提供有关哪些是到期的最佳候选者的提示,请使用volatile-ttl。

当您要使用单个实例进行缓存并拥有一组持久键时,volatile-lru和volatile-random策略主要有用。 但是,通常最好运行两个Redis实例来解决此问题。

还值得注意的是,将键设置为过期会消耗内存,因此使用诸如allkeys-lru之类的策略会提高内存效率,因为无需为在内存压力下驱逐密钥设置过期。

1.3.驱逐过程如何进行

重要的是要了解驱逐过程的工作方式如下:

  • 客户端运行新命令,从而添加更多数据。
  • Redis会检查内存使用情况,如果大于最大内存限制,则会根据策略逐出键。
  • 执行新命令,依此类推。

因此,我们越过了内存限制,然后通过逐出按键以在限制范围内返回,来不断越过内存限制的边界。

如果某条命令导致一段时间内使用了大量内存(例如将较大的交集存储到新键中),则内存限制可能会超出明显的数量。

1.4.近似LRU算法

Redis LRU算法不是确切的实现。 这意味着Redis无法选择最好的驱逐对象,即过去访问最多的访问。 取而代之的是,它将尝试对LRU算法进行近似处理,方法是对少量键进行采样,然后从采样的键中驱出最好的(访问时间最长)键。

但是,自Redis 3.0起,对该算法进行了改进,使其还可以收集一批优秀的驱逐对象。 这改善了算法的性能,使其能够更接近地逼真的LRU算法的行为。

Redis LRU算法的重要意义在于,您可以通过更改样本数量来检查每次逐出,从而调整算法的精度。 此参数由以下配置指令控制:

maxmemory-samples 5

Redis之所以不使用真正的LRU实现,是因为它占用更多内存。 但是,近似值实际上与使用Redis的应用程序等效。 以下是Redis使用的LRU近似与真实LRU比较的图形比较。

LRU comparison

生成上述图形的测试用给定数量的键填充了Redis服务器。 键是从第一个到最后一个访问的,因此第一个键是使用LRU算法驱逐的最佳候选者。 后来又添加了50%的键,以强制淘汰一半的旧键。

您可以在图形中看到三种点,形成三个不同的带。

  • 浅灰色带是被逐出的对象。
  • 灰带是未被逐出的对象。
  • 绿带是添加的对象。

在理论上的LRU实现中,我们期望在旧键中,前半部分将过期。 相反,Redis LRU算法只会概率地使较早的键过期。

如您所见,与Redis 2.8相比,Redis 3.0在5个样本上做得更好,但是Redis 2.8仍然保留了最新访问的对象中的大多数。 在Redis 3.0中使用10的样本大小,近似值非常接近Redis 3.0的理论性能。

请注意,LRU只是一个模型,用于预测将来将访问给定键的可能性。 此外,如果您的数据访问模式与幂律极为相似,则大多数访问将位于LRU近似算法将能够很好处理的键集中。

在仿真中,我们发现使用幂定律访问模式,真实LRU和Redis近似之间的差异很小或根本不存在。

但是,您可以以一些额外的CPU使用为代价将样本大小增加到10,以接近真实的LRU,并检查这是否会导致高速缓存未命中率有所不同。

通过使用 CONFIG SET maxmemory-samples <count>  命令以不同的样本大小值进行生产实验非常简单。

1.5.新的LFU模式

从Redis 4.0开始,可以使用新的“最少使用”逐出模式( Least Frequently Used eviction mode)。 在某些情况下,此模式可能会更好地工作(提供更好的命中率/未命中率),因为使用LFU Redis会尝试跟踪物品的访问频率,因此,很少使用的物品会被驱逐,而经常使用的物品则有较高的机会保留在内存中。

如果您认为在LRU,最近访问过但实际上几乎从未请求过的项目不会过期,因此风险在于逐出将来有更高机会被要求使用的钥匙。 LFU没有这个问题,通常应该更好地适应不同的访问模式。

要配置LFU模式,可以使用以下策略:

  • volatile-lfu 使用具有过期集的键在近似的LFU中进行驱逐。
  • allkeys-lfu 使用近似的LFU退出任何键。

LFU近似于LRU:它使用一个概率计数器(称为莫里斯计数器),以便仅使用每个对象几个位来估计对象访问频率,并结合一个衰减周期,从而使计数器随时间而减少:在某个时候,我们甚至不再希望将键视为过去经常访问的键,因此该算法可以适应访问模式的转变。

这些信息的采样方式与LRU发生的情况类似(如本文档前面部分所述),以选择驱逐候选人。

但是,与LRU不同,LFU具有某些可调参数:例如,如果频繁访问的项不再受访问,应该将其降低多快? 还可以调整Morris计数器范围,以使算法更好地适应特定的用例。

默认情况下,Redis 4.0配置为:

  • 在大约一百万个请求时使计数器饱和。
  • 每隔一分钟使计数器衰减一次。

这些应该是合理的值,并经过实验测试,但是用户可能希望使用这些配置设置来选择最佳值。

可以在源代码发行版的示例redis.conf文件中找到有关如何调整这些参数的说明,但简要地说,它们是:

lfu-log-factor 10
lfu-decay-time 1

衰减时间是显而易见的时间,它是在采样时发现计数器早于该值应衰减的分钟数。 特殊值0表示:每次扫描时总是使计数器衰减,并且很少有用。

计数器对数因子会更改要使频率计数器达到饱和所需的命中次数,频率计数器刚好在0-255的范围内。 因数越高,为了达到最大值需要更多的访问。 根据下表,系数越低,计数器的分辨率越低,分辨率越高:

+--------+------------+------------+------------+------------+------------+
| factor | 100 hits   | 1000 hits  | 100K hits  | 1M hits    | 10M hits   |
+--------+------------+------------+------------+------------+------------+
| 0      | 104        | 255        | 255        | 255        | 255        |
+--------+------------+------------+------------+------------+------------+
| 1      | 18         | 49         | 255        | 255        | 255        |
+--------+------------+------------+------------+------------+------------+
| 10     | 10         | 18         | 142        | 255        | 255        |
+--------+------------+------------+------------+------------+------------+
| 100    | 8          | 11         | 49         | 143        | 255        |
+--------+------------+------------+------------+------------+------------+

因此,基本上,因素是在具有较低访问权限的更好区分项与具有较高访问权限的区分项之间进行权衡。 更多信息可在示例redis.conf文件自我记录注释中获得。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

琴 韵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值