原文地址:https://redis.io/topics/lru-cache

Redis可以用来作缓存,他可以很方便的淘汰(删除)旧数据添加新数据,类似memcached。LRU只是其中的一种置换算法,这篇文章介绍了maxmemory配置命令和LRU算法的一些深入讨论,这里的LRU只是一种近似LRU(并不是严格的把最老的数据淘汰,而是使用随机采样的方式)。从4.0开始Redis引入了一种新的淘汰算法LFU(Least Frequently Used)。

maxmemory配置命令

maxmemory配置命令用来指定Redis存储数据的大小,可以在redis.conf里配置,也可以运行的时候用CONFIG SET配置。比如配置成使用100M内存,配置命令如下

maxmemory 100mb

如果把maxmemory设置成0就是不对内存使用量做限制。在64位系统上默认是设置成0,在32位系统上默认设置成3GB。如果达到了限制内存,会根据配置采取不同的策略,可以给相应的命令返回错误,也可以淘汰旧数据来存入新数据。

淘汰策略

在配置文件里使用maxmemory-policy命令指定淘汰策略,取值如下

  • noeviction:达到限制内存以后再存新数据会返回出错。
  • allkeys-lru:淘汰最近没使用的数据。
  • volatile-lru:在设置了过期值(expire)的数据里淘汰最近没使用的数据。
  • allkeys-random:随机淘汰数据。
  • volatile-random:在设置了过期值(expire)的数据里随机淘汰数据。
  • volatile-ttl:在设置了过期值(expire)的数据里淘汰快要过期的数据。

volatile-lru,volatile-random和volatile-ttl在没有可淘汰的数据的时候也会像noeviction一样返回出错。怎样选择淘汰策略取决于你的程序,也可以在使用的过程中用INFO命令观察命中率再做调整。一般情况按如下方法选择淘汰策略:

  • 如果所存储的数据访问量成幂律分布的,也就是说一部分数据的访问量明显多于其他数据,那么就使用allkeys-lru。
  • 如果所存储的数据周期访问的,或者被访问的概率大致相同,那么就是用allkeys-random。
  • 如果所存储的数据设置了不同的过期时间,可以用volatile-ttl。

如果在一个redis实例里存储了两种数据(永久数据和带过期时间的数据),使用volatile-lru和volatile-random是比较好的选择。当然更好的办法是把这两种数据分别存在一个redis实例里。给数据设置过期时间是需要消耗内存的,所以使用allkeys-lru会更节省内存。

淘汰数据的过程

  • 客户端请求添加数据。
  • redis检查内存是否超过了maxmemory限制,如果超过了就根据策略淘汰旧数据。
  • 添加客户端要求的添加的数据。

所以内存使用量会一直在maxmemory上下徘徊,如果某个命令要求添加一个很大的数据很可能造成redis使用的内存明显超过了maxmemory限制。

近似LRU算法

redis的LRU没有严格的实现LRU,也就是说redis不是淘汰最佳(最久没访问)的数据。redis会做一个随机采样,淘汰样本里最佳数据。3.0以后redis会使用备选池做淘汰,提升了性能,准确性更高,更接近LRU算法(代码里提升性能很明显,准确率更高这点看不出来,可能官方做统计得出的结论)。可以设置样本大小调整算法的准确率。

maxmemory-samples 5

redis没用真正的LRU实现是因为这正的LRU太消耗内存了,要遍历排序,会慢很多。下图是近似LRU算法和真正的LRU算法的测试对比图

测试的时候先生成一些数据。从第一个数据开始存储,一直到最后一个,所以第一个数据是LRU算法的最佳淘汰对象。最后又添加50%的数据用来淘汰旧数据。上面的三个色带分别是:

  • 浅灰色是淘汰的数据
  • 灰色是没有淘汰的数据
  • 绿色是新添加的数据。

理论上最先添加的一半数据应该淘汰,redis的LRU算法只是概率性的淘汰这些旧数据。可以看出来在maxmemory-samples设置成5的时候3.0版本比2.8版本更精确(相对来说更接近理论值)。maxmemory-samples设置成10的时候3.0版本已经相对接近理论值了。

LRU只是预测将来一段时间的数据访问模型,如果你的数据成幂律分布redis的LRU也能非常好的处理这个模型。 redis的LRU和真正的LRU差距非常小甚至没差距。如果想要更接近LRU可以提高样本采集量把maxmemory-samples设置成10。

新的近似LFU模式

从4.0开始redis引入了一个新的淘汰模型LFU(Least Frequently Used)。一些情况下这个模型在命中率上更会准确。LFU会统计数据的使用率,使用率低的会被淘汰,使用率高的留下。LRU会保留最近访问了但是平常访问率很低的数据,风险就是淘汰了一个平常访问率高但是最近没访问的数据。LFU不会存在这样的问题,所以LFU更适用于各种不同的访问模型。LFU策略配置如下:

  • volatile-lfu:在设置了过期时间的数据里使用近似LFU淘汰算法。
  • allkeys-lfu:在所有的数据上使用LFU淘汰算法。

LFU和LRU类似也是一种概率计算,LFU使用一个叫morris counter的概率统计方法,一个数据只使用几个比特。和一个叫过期时间(decay period)的数结合使用。统计值(counter)随着时间减小。LFU也是使用采样的方式淘汰数据。LFU有更多的调整选项,4.0默认的配置

  • 一百万访问量会使统计值(counter)变为最大
  • 衰败期是一分钟

这些是经过测试比较好用的,用户也可以自己设置。配置命令如下:

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里有更详细的说明。

近似LFU算法

  1. 取一个0到1之间的随机值R
  2. 计算P=1/(old_value*lfu_log_factor+1),这里的old_value就是上面说的counter值。
  3. 当R<P的时候counter加一。

不是学数学的不会证明这个算法,但是看起来这个算法本身不难,也是用的概率的方法,访问量和counter值之间大概是指数关系,用的时候参考上面那个表就行了。

用redis当作LRU缓存的更多相关文章

  1. Redis学习笔记2-使用 Redis 作为 LRU 缓存

    当 Redis 作为缓存使用时,当你添加新的数据时,有时候很方便使 Redis 自动回收老的数据.LRU 实际上是被唯一支持的数据移除方法.Redis 的 maxmemory 指令,用于限制内存使用到 ...

  2. Redis - 作为 LRU 缓存

    一.简介 LRU 实际上是被唯一支持的数据移除方法,同时也是 memcached 默认支持的缓存算法. 二.配置内存大小 在 redis.conf 文件中使用 maxmemory 指令能够配置内存大小 ...

  3. Redis作为lru缓存作用

    当 Redis 作为缓存使用时,当你添加新的数据时,有时候很方便使 Redis 自动回收老的数据.LRU 实际上是被唯一支持的数据移除方法.Redis 的 maxmemory 指令,用于限制内存使用到 ...

  4. redis(7)LRU缓存

    一.LRU简介 LRU是Least Recently Used的缩写,即:最近最少使用. 它是内存管理中的一种页面置换算法,对于在内存中但是又不用的数据块,操作系统会根据哪些数据属于LRU而将其移除内 ...

  5. Redis做LRU缓存

    当Redis用作缓存时,通常可以让它在添加新数据时自动逐出旧数据. 这种行为在开发人员社区中非常有名,因为它是流行的memcached系统的默认行为. LRU实际上只是支持的驱逐方法之一. 本页介绍了 ...

  6. redis文档翻译_LRU缓存

    Using Redis as an LRU cache使用Redis作为LRU缓存 出处:http://blog.csdn.net/column/details/redisbanli.html Whe ...

  7. 动手实现 LRU 算法,以及 Caffeine 和 Redis 中的缓存淘汰策略

    我是风筝,公众号「古时的风筝」. 文章会收录在 JavaNewBee 中,更有 Java 后端知识图谱,从小白到大牛要走的路都在里面. 那天我在 LeetCode 上刷到一道 LRU 缓存机制的问题, ...

  8. 在我们使用Redis作为一个LRU缓存的时候,怎么做才能更高效

    当用Redis作为一个LRU存储时,有些时候是比较方便的,在你增添新的数据时会自动驱逐旧的数据.这种行为在开发者论坛是非常有名的,因为这是流行的memcached系统的默认行为. LRU实际上只是支持 ...

  9. Redis只作为缓存,不做持久化的配置

    #1.配置缓存内存限制和清理策略 #作为缓存服务器,如果不加以限制内存的话,就很有可能出现将整台服务器内存都耗光的情况,可以在redis的配置文件里面设置: #example: # 限定最多使用1.5 ...

随机推荐

  1. 当this碰到return会发生什么

    当this碰到return时 function fn(params) { this.user = 'fzy' return {} } var a = new fn console.log(a.user ...

  2. 跟着兄弟连系统学习Linux-【day03】

    day03-20200529 p10.学习注意事项         linux严格区分大小写(与python有点像)         Linux中所有内容都是通过文件形式保存,通过命令执行设置参数,写 ...

  3. 2048游戏 - C语言不引入图形库简单实现

    声明:本程序绝大部分属于原创,交互部分参考了博客园 Judge Young的原创文章 游戏2048源代码 - C语言控制台界面版, 作者Judge Young的算法思想非常值得参考,感谢作者的分享 附 ...

  4. 关于Vuex的那些事儿

    vuex vuex是一个专门为Vue.js应用程序开发的状态管理模式,集中式的存储应用的所有组件的状态 以相应的规则保证状态以一种可预测的方式发生变化 单向数据流 State:驱动应用的数据源(单向数 ...

  5. leetcode刷题-62不同路径

    题目 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” ). 机器人每次只能向下或者向右移动一步.机器人试图达到网格的右下角(在下图中标记为“Finish”). 问总 ...

  6. Spring-代理模式

    代理模式 目录 代理模式 1. 代理模式的分类 2. 静态代理 1. 角色分析 2. 代码步骤 3. 代理的好处 4. 进一步理解 3. 动态代理 1. 角色分析 2. 对动态代理的两个关键类的理解 ...

  7. 设计模式也可以这么简单(7年开发老鸟PS注释总结)

    设计模式是对大家实际工作中写的各种代码进行高层次抽象的总结,其中最出名的当属 Gang of Four (GoF) 的分类了,他们将设计模式分类为 23 种经典的模式,根据用途我们又可以分为三大类,分 ...

  8. 【微信小程序】常用组件及自定义组件

    (一) 常用标签 组件你可以理解为传统页面开发时候的各种标签,例如 div span 等等,我这里只说一些常用的,这样就能能搭建出一个基本的页面了,但是如果想要更加美观以及拥有更好的体验,就需要 XS ...

  9. 5 分钟带你掌握 Makefile 分析

    摘要:Makefile是一个名为GNU-Make软件所需要的脚本文件,该脚本文件可以指导Make软件控制arm-gcc等工具链去编译工程文件最终得到可执行文件,几乎所有的Linux发行版都内置了GNU ...

  10. oracle之三存储库及顾问框架

    AWR存储库及顾问框架(PPT-I-349-360) 14.1 Oracle数据库采样ASH和AWR. 1) ASH(Active Session History) ASH收集的是活动会话的样本数据, ...