Use redis as a cache using the LRU algorithm

When Redis is used as a cache, it is convenient to have it automatically recycle old data when you add new data. This behavior is well known in the developer community because it is the default behavior of the popular memcached system.

LRU is the only recycling method supported by Redis. This page covers some general topics, Redis' maxmemoryinstructions for limiting available memory to a fixed size, and the LRU algorithm used by Redis, which is really just an approximate LRU.

Maxmemory configuration directives

maxmemoryThe configuration directive is used to configure the memory size of the limit when Redis stores data. This directive can be set via redis.conf, or later configured using the CONFIG SET command.

For example to configure the memory limit to 100mb, the following directives can be placed in the redis.conffile.

maxmemory 100mb

Set maxmemoryto 0 for no memory limit. This is the default value for 64-bit systems, and the default memory limit for 32-bit systems is 3GB.

When the specified memory limit size is reached, a different behavior, or strategy , needs to be selected . Redis can just return an error on the command, which will make more memory used, or recycle some old data so that the memory limit can be avoided when adding data.

recycling strategy

The behavior that Redis will use when the maxmemory limit is reached is configured by the Redis maxmemory-policy configuration directive.

The following strategies are available:

  • noeviction : returns an error when the memory limit is reached and the client tries to execute a command that would cause more memory to be used (most write commands, but DEL and a few exceptions)
  • allkeys-lru : Attempt to reclaim the least used keys (LRU) to make room for newly added data.
  • volatile-lru : Attempt to reclaim the least used key (LRU), but only on keys in the expired set, making room for newly added data.
  • allkeys-random : Reclaim random keys to make room for newly added data.
  • volatile-random : Reclaims random keys to make room for newly added data, but only for keys in expired sets.
  • volatile-ttl : Reclaim keys in expired sets, and give priority to keys with shorter time-to-live (TTL), so that newly added data has space to store.

The strategies volatile-lruvolatile-random and volatile-ttl are similar to noeviction if no keys satisfy the preconditions for recycling .

It is very important to choose the correct recycling strategy, which depends on the access pattern of your application, but you can make relevant policy adjustments at runtime, and monitor the cache hit rate and number of misses, and output them through the RedisINFO command for tuning. .

General rule of thumb:

  • Use the allkeys-lru strategy: when you want your requests to follow a power-law distribution, that is, you want some subset of elements to be accessed more than other elements. This is a great option if you're not sure what to choose. .
  • Use allkeys-random : If you are iterating, all keys are scanned consecutively, or you want the request distribution to be normal (all elements are accessed with similar probability).
  • Use volatile-ttl : if you want to decide which objects should be expired by setting the TTL value when creating the cached object.

allkeys-lru 和 volatile-random策略对于当你想要单一的实例实现缓存及持久化一些键时很有用。不过一般运行两个实例是解决这个问题的更好方法。

为了键设置过期时间也是需要消耗内存的,所以使用allkeys-lru这种策略更加高效,因为没有必要为键取设置过期时间当内存有压力时。

回收进程如何工作

理解回收进程如何工作是非常重要的:

  • 一个客户端运行了新的命令,添加了新的数据。
  • Redi检查内存使用情况,如果大于maxmemory的限制, 则根据设定好的策略进行回收。
  • 一个新的命令被执行,等等。
  • 所以我们不断地穿越内存限制的边界,通过不断达到边界然后不断地回收回到边界以下。

如果一个命令的结果导致大量内存被使用(例如很大的集合的交集保存到一个新的键),不用多久内存限制就会被这个内存使用量超越。

近似LRU算法

Redis的LRU算法并非完整的实现。这意味着Redis并没办法选择最佳候选来进行回收,也就是最久未被访问的键。相反它会尝试运行一个近似LRU的算法,通过对少量keys进行取样,然后回收其中一个最好的key(被访问时间较早的)。

不过从Redis 3.0算法已经改进为回收键的候选池子。这改善了算法的性能,使得更加近似真是的LRU算法的行为。

Redis LRU有个很重要的点,你通过调整每次回收时检查的采样数量,以实现调整算法的精度。这个参数可以通过以下的配置指令调整:

maxmemory-samples 5

Redis为什么不使用真实的LRU实现是因为这需要太多的内存。不过近似的LRU算法对于应用而言应该是等价的。使用真实的LRU算法与近似的算法可以通过下面的图像对比。

LRU comparison

用于生成图像的Redis服务被填充了指定数量的键。这些键将被从头到尾访问,所以当使用LRU算法时第一个键是最佳的回收候选键。接着添加超过50%的键,用于强制旧键被回收。

你可以看到三种点在图片中, 形成了三种带.

  • 浅灰色带是已经被回收的对象。
  • 灰色带是没有被回收的对象。
  • 绿色带是被添加的对象。
  • 在LRU实现的理论中,我们希望的是,在旧键中的第一半将会过期。Redis的LRU算法则是概率的过期旧的键。

你可以看到,在都是五个采样的时候Redis 3.0比Redis 2.8要好,Redis2.8中在最后一次访问之间的大多数的对象依然保留着。使用10个采样大小的Redis 3.0的近似值已经非常接近理论的性能。

注意LRU只是个预测键将如何被访问的模型。另外,如果你的数据访问模式非常接近幂定律,大部分的访问将集中在一个键的集合中,LRU的近似算法将处理得很好。

在模拟实验的过程中,我们发现如果使用幂定律的访问模式,则真实的LRU算法和近似的Redis算法几乎没有差别。

当然你可以提升采样大小到10,消耗更多的CPU时间以实现更真实的LRU算法,同时查看下是否让你的缓存命中率有差别。

通过CONFIG SET maxmemory-samples 命令在生产环境上设置不同的采样大小是非常简单的。

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326591055&siteId=291194637