Redis 缓存逐出策略

  • 把 Redis 当作缓存使用时,有时你能够方便的让它在新数据时自动逐出旧数据。这一点你们都比较清楚,由于 memcached 默认也会这么干redis

  • Redis 仅支持 LRU 逐出策略。下文主要讲述 Redis maxmemory 指令,这个指令用于限定内存使用量,以及讲述了 Redis 使用到的 LRU 算法,这是一种近似LRU算法。算法

  • maxmemory 配置指令缓存

    • maxmemory 指令用于限定内存使用量。能够在 redis.conf 文件中设置,也能够经过 CONFIG SET 命令在运行时设置。dom

    • 例如在 redis.conf 文件中添加以下指令将内存限定在 100M 之内memcached

      • maxmemory 100mb性能

    • 设置成 0 时表示无限制。64位系统下默认无限制,32位系统则强制指定为 3GBspa

    • 当内存使用达到限定值时,能够选择几种不一样的策略。例如 Redis 能够在调用指令时直接返回错误(这些指令会致使更多内存使用),或者是逐出老数据,给新数据纳出空间,让内存占用保持在限定一下。对象

  • 逐出策略ip

    • 具体的逐出策略经过 maxmemory-policy 指令进行配置,主要有以下策略:内存

      • noeviction:调用某些指令时返回错误(主要是绝大多数的写指令,DEL 和 部分其余指令不包括)

      • allkeys-lru:对全键进行LRU

      • volatile-lru:对指定了过时时间(expire set)的键进行LRU

      • allkeys-random:对全键进行随机逐出

      • volatile-random:对指定了过时时间的键随机逐出

      • volatile-ttl:对指定了过时时间,而且 TTL 较短的键进行逐出

    • volatile-* 系列指令在无键值知足条件时(例如未设置过时时间),表现为 noeviction

    • 不一样的应用选择不一样的逐出策略,固然你能够根据命中率(INFO指令)在运行时动态调整策略。

    • 能够参考如下的经验法则:

      • allkeys-lru,预期的请求符合长尾理论。或是啥都不懂时配成这个不会太差

      • allkeys-random,会持续轮询全部的键。或者预期的请求符合均匀分布

      • volatile-ttl,在生成缓存对象时指定不一样的 ttl 值,因此你得控制好

    • 你在单实例上同时存储缓存数据,以及一些持久化数据时,volatile-lru 和 volatile-random 会比较适合。可是一般建议缓存数据和持久化数据用不一样的实例存储。

    • 另外,对一个键设置过时时间会占用额外的内存,因此在内存压力较大时 allkeys-lru 的内存使用率会较好。

  • 逐出过程是如何实现的

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

      • 客户端运行了一个消耗内存的指令

      • Redis 检查内存占用后发现超限,执行逐出策略

      • 执行一个新的指令,如此循环

    • 即反复的让 Redis 的内存占用在限定值上下波动,来观察和验证逐出策略

    • 当一个指令消耗较多内存时,必定时间范围内能够观察到明显的内存超限

  • 近似LRU算法

    • Redis 使用的 LRU 算法是一个近似实现,即逐出Key并不必定真正访问最少的键。它采用的方式是,对逐出范围内的键进行采样,而后对样本进行逐出。什么鬼。

    • 在 Redis 3.0中有了一些改进,在提高性能的同时,让近似LRU的结果更加接近真实LRU。

    • Redis LRU挺重要的一点是,你能够调整算法精度,即调整每次逐出时的取样数。能够经过这个指令进行调整:

      • maxmemory-samples 5

    • Redis 使用 近似LRU 的目的主要仍是为了节省内存,对于应用来讲,近似与真实,其实是等效的。

    clipboard.png

  • 在 Redis 中填充满指定数目的数据,顺序访问全部的键,在LRU下,第一个键是最佳逐出对象。而后增长50%的键值,逐出一半的老数据。

  • 图中的三种点造成了三条不一样的条纹

    • 浅灰色表示已经逐出的

    • 灰色表示未被逐出的

    • 绿色表示新增的

  • 理论LRU的结果彻底符合预期,前一半的老数据逐出。Redis LRU 则是几率上的逐出老数据。

  • 能够看到,取样数为5时,Redis 3.0 比 Redis 2.8 效果要好不少,2.8逐出了很多刚刚被访问过的数据。取样数为10时,Redis 3.0 的表现跟理论LRU就很是接近了。

  • 若是请求符合长尾法则,那么真实LRU与Redis LRU之间表现基本无差别。

  • 你能够在增长必定CPU消耗的状况下,提升取样数,而后检查命中率是否有变化

  • 在生产环境,经过 CONFIG SET maxmemory-samples <count> 指令能够方便的设置取样数。

相关文章
相关标签/搜索