Redis缓存逐出策略

《Redis缓存逐出策略》


    把 Redis 当做缓存使用时,有时你可以方便的让它在新数据时自动逐出旧数据。这一点大家都比较清楚,因为 memcached 默认也会这么干。Redis 仅支持 LRU 逐出策略。下文主要讲述 Redis maxmemory 指令,这个指令用于限定内存使用量,以及讲述了Redis 使用到的 LRU 算法,这是一种近似LRU算法。

1. maxmemory 配置指令

    maxmemory 指令用于限定内存使用量。可以在 redis.conf 文件中设置,也可以通过 CONFIG SET 命令在运行时设置。例如在 redis.conf 文件中添加如下指令将内存限定在 100M 以内maxmemory 100MB。
  1. 设置成 0 时表示无限制。64位系统下默认无限制,32位系统则强制指定为 3GB
  2. 当内存使用达到限定值时,可以选择几种不同的策略。例如 Redis 可以在调用指令时直接返回错误(这些指令会导致更多内存使用),或者是逐出老数据,给新数据纳出空间,让内存占用保持在限定一下。

2. 逐出策略

具体的逐出策略通过 maxmemory-policy 指令进行配置,主要有如下策略:
  1. noeviction:当内存使用达到阈值的时候,所有引起申请内存的命令会报错。
  2. allkeys-lru:在主键空间中,优先移除最近未使用的key。
  3. volatile-lru:在设置了过期时间的键空间中,优先移除最近未使用的key。
  4. allkeys-random:在主键空间中,随机移除某个key。
  5. volatile-random:在设置了过期时间的键空间中,随机移除某个key。
  6. volatile-ttl:在设置了过期时间的键空间中,具有更早过期时间的key优先移除。
  7. volatile-* 系列指令在无键值满足条件时(例如未设置过期时间),表现为 noeviction
    这里补充一下主键空间和设置了过期时间的键空间,举个例子,假设我们有一批键存储在Redis中,则有那么一个哈希表用于存储这批键及其值,如果这批键中有一部分设置了过期时间,那么这批键还会被存储到另外一个哈希表中,这个哈希表中的值对应的是键被设置的过期时间。设置了过期时间的键空间为主键空间的子集。
    我们了解了Redis大概提供了这么几种淘汰策略,那么如何选择呢?淘汰策略的选择可以通过下面的配置指定: # maxmemory-policy noeviction
    但是这个值填什么呢?为解决这个问题,我们需要了解我们的应用请求对于Redis中存储的数据集的访问方式以及我们的诉求是什么。同时Redis也支持Runtime修改淘汰策略,这使得我们不需要重启Redis实例而实时的调整内存淘汰策略。

3 几种策略的适用场景

  • allkeys-lru:如果我们的应用对缓存的访问符合幂律分布(也就是存在相对热点数据),或者我们不太清楚我们应用的缓存访问分布状况,我们可以选择allkeys-lru策略。
  • allkeys-random:如果我们的应用对于缓存key的访问概率相等,则可以使用这个策略。
  • volatile-ttl:这种策略使得我们可以向Redis提示哪些key更适合被eviction。
    另外,volatile-lru策略和volatile-random策略适合我们将一个Redis实例既应用于缓存和又应用于持久化存储的时候,然而我们也可以通过使用两个Redis实例来达到相同的效果,值得一提的是将key设置过期时间实际上会消耗更多的内存,因此我们建议使用allkeys-lru策略从而更有效率的使用内存。

4 逐出过程是如何实现的

最好从以下几个方面来了解逐出过程

  1. 客户端运行了一个消耗内存的指令;
  2. Redis 检查内存占用后发现超限,执行逐出策略;
  3. 执行一个新的指令,如此循环;
  4. 即反复的让 Redis 的内存占用在限定值上下波动,来观察和验证逐出策略;
  5. 当一个指令消耗较多内存时,一定时间范围内可以观察到明显的内存超限;

5 近似LRU算法

    Redis 使用的 LRU 算法是一个近似实现,即逐出Key并不一定真正访问最少的键。它采用的方式是,对逐出范围内的键进行采样,然后对样本进行逐出。什么鬼。
    在 Redis 3.0中有了一些改进,在提升性能的同时,让近似LRU的结果更加接近真实LRU。
    Redis LRU挺重要的一点是,你可以调整算法精度,即调整每次逐出时的取样数。可以通过这个指令进行调整:
    Redis 使用 近似LRU 的目的主要还是为了节省内存,对于应用来说,近似与真实,实际上是等效的。

你可能感兴趣的:(Redis)