LRU(Least Recently Used) 最近最少使用算法是众多置换算法中的一种。

Redis中有一个 maxmemory 概念,主要是为了将使用的内存限定在一个固定的大小。Redis 用到的 LRU 算法,是一种近似的LRU算法。

1、设置 maxmemory

上面已经说过 maxmemory 是为了限定 Redis 最大内存使用量。有多种方法设定它的大小。其中一种方法是通过 CONFIG SET 设定,如下:

127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "0"
127.0.0.1:6379> CONFIG SET maxmemory 100MB
OK
127.0.0.1:6379> CONFIG GET maxmemory
1) "maxmemory"
2) "104857600"

另一种方法是修改配置文件 redis.conf

maxmemory 100mb

注意,在 64bit 系统下,maxmemory 设置为 0 表示不限制 Redis 内存使用,在 32bit 系统下,maxmemory 隐式不能超过 3GB。

当 Redis 内存使用达到指定的限制时,就需要选择一个置换的策略。

2、置换策略

当 Redis 内存使用达到 maxmemory 时,需要选择设置好的 maxmemory-policy 进行对老数据的置换。

下面是可以选择的置换策略:

  • noeviction: 不进行置换,表示即使内存达到上限也不进行置换,所有能引起内存增加的命令都会返回error
  • allkeys-lru: 优先删除掉最近最不经常使用的key,用以保存新数据
  • volatile-lru: 只从设置失效(expire set)的key中选择最近最不经常使用的key进行删除,用以保存新数据
  • allkeys-random: 随机从all-keys中选择一些key进行删除,用以保存新数据
  • volatile-random: 只从设置失效(expire set)的key中,选择一些key进行删除,用以保存新数据
  • volatile-ttl: 只从设置失效(expire set)的key中,选出存活时间(TTL)最短的key进行删除,用以保存新数据

设置 maxmemory-policy 的方法 和 设置 maxmemory 方法类似,通过 redis.conf 或是通过 CONFIG SET 动态修改。

如果没有匹配到可以删除的 key,那么 volatile-lruvolatile-random 和 volatile-ttl 策略和 noeviction 替换策略一样——不对任何 key 进行置换。

选择合适的置换策略是很重要的,这主要取决于你的应用的访问模式,当然你也可以动态的修改置换策略,并通过用 Redis 命令——INFO 去输出 cache 的命中率情况,进而可以对置换策略进行调优。

一般来说,有这样一些常用的经验:

  • 在所有的 key 都是最近最经常使用,那么就需要选择 allkeys-lru 进行置换最近最不经常使用的 key,如果你不确定使用哪种策略,那么推荐使用 allkeys-lru
  • 如果所有的 key 的访问概率都是差不多的,那么可以选用 allkeys-random 策略去置换数据
  • 如果对数据有足够的了解,能够为 key 指定 hint(通过expire/ttl指定),那么可以选择 volatile-ttl 进行置换

volatile-lru 和 volatile-random 经常在一个Redis实例既做cache又做持久化的情况下用到,然而,更好的选择使用两个Redis实例来解决这个问题。

设置是失效时间 expire 会占用一些内存,而采用 allkeys-lru 就没有必要设置失效时间,进而更有效的利用内存。

3、置换策略是如何工作的

理解置换策略的执行方式是非常重要的,比如:

  • 客户端执行一条新命令,导致数据库需要增加数据(比如set key value)
  • Redis会检查内存使用,如果内存使用超过 maxmemory,就会按照置换策略删除一些 key
  • 新的命令执行成功

我们持续的写数据会导致内存达到或超出上限 maxmemory,但是置换策略会将内存使用降低到上限以下。

如果一次需要使用很多的内存(比如一次写入一个很大的set),那么,Redis 的内存使用可能超出最大内存限制一段时间。

4、近似 LRU 算法

Redis 中的 LRU 不是严格意义上的LRU算法实现,是一种近似的 LRU 实现,主要是为了节约内存占用以及提升性能。Redis 有这样一个配置 —— maxmemory-samples,Redis 的 LRU 是取出配置的数目的key,然后从中选择一个最近最不经常使用的 key 进行置换,默认的 5,如下:

maxmemory-samples 5

可以通过调整样本数量来取得 LRU 置换算法的速度或是精确性方面的优势。

Redis 不采用真正的 LRU 实现的原因是为了节约内存使用。虽然不是真正的 LRU 实现,但是它们在应用上几乎是等价的。下图是 Redis 的近似 LRU 实现和理论 LRU 实现的对比:

测试开始首先在 Redis 中导入一定数目的 key,然后从第一个 key 依次访问到最后一个key,因此根据 LRU 算法第一个被访问的 key 应该最新被置换,之后再增加 50% 数目的 key,导致 50% 的老的 key 被替换出去。

在上图中你可以看到三种类型的点,组成三种不同的区域:

  • 淡灰色的是被置换出去的key
  • 灰色的是没有被置换出去的key
  • 绿色的是新增加的key

理论 LRU 实现就像我们期待的那样,最旧的 50% 数目的 key 被置换出去,Redis 的 LRU 将一定比例的旧 key 置换出去。

可以看到在样本数为 5 的情况下,Redis3.0 要比 Redis2.8 做的好很多,Redis2.8 中有很多应该被置换出去的数据没有置换出去。在样本数为10的情况下,Redis3.0 很接近真正的 LRU 实现。

LRU 是一个预测未来我们会访问哪些数据的模型,如果我们访问数据的形式接近我们预想——幂律,那么近似 LRU 算法实现将能处理的很好。

在模拟测试中我们可以发现,在幂律访问模式下,理论 LRU 和 Redis 近似 LRU 的差距很小或者就不存在差距。

如果你将 maxmemory-samples 设置为 10,那么 Redis 将会增加额外的 CPU 开销以保证接近真正的 LRU 性能,可以通过检查命中率来查看有什么不同。

通过 CONFIG SET maxmemory-samples <count> 动态调整样本数大小,做一些测试验证你的猜想。

参考:

http://redis.io/topics/lru-cache

Redis中的maxmemory怎么设置?

Redis内存使用达到maxmemory设定值后玩家数据无法写入解决

Redis系列之三生产环境实战须知

Redis 缓存过期(maxmemory) 配置/算法 详解的更多相关文章

  1. Redis数据过期和淘汰策略详解(转)

    原文地址:https://yq.aliyun.com/articles/257459# 背景 Redis作为一个高性能的内存NoSQL数据库,其容量受到最大内存限制的限制. 用户在使用Redis时,除 ...

  2. Redis(二十):Redis数据过期和淘汰策略详解(转)

    原文地址:https://yq.aliyun.com/articles/257459# 背景 Redis作为一个高性能的内存NoSQL数据库,其容量受到最大内存限制的限制. 用户在使用Redis时,除 ...

  3. 高并发架构系列:Redis缓存和MySQL数据一致性方案详解

    一.需求起因 在高并发的业务场景下,数据库大多数情况都是用户并发访问最薄弱的环节.所以,就需要使用redis做一个缓冲操作,让请求先访问到redis,而不是直接访问MySQL等数据库. 这个业务场景, ...

  4. redis.conf配置信息详解

    redis.conf配置信息详解 配置文件 # Redis 配置文件 # 当配置中需要配置内存大小时,可以使用 1k, 5GB, 4M 等类似的格式,其转换方式如下(不区分大小写) # # 1k =& ...

  5. Redis配置参数详解

    Redis配置参数详解 /********************************* GENERAL *********************************/ // 是否作为守护进 ...

  6. reids配置参数详解

    转自:http://www.jb51.net/article/60627.htm reids配置参数详解 #daemonize no  默认情况下, redis 不是在后台运行的,如果需要在后台运行, ...

  7. 【第六课】Nginx常用配置下详解

    目录 Nginx常用配置下详解 1.Nginx虚拟主机 2.部署wordpress开源博客 3.部署discuz开源论坛 4.域名重定向 5.Nginx用户认证 6.Nginx访问日志配置 7.Ngi ...

  8. (转)nginx日志配置指令详解

    这篇文章主要介绍了nginx日志配置指令详解,nginx有一个非常灵活的日志记录模式,每个级别的配置可以有各自独立的访问日志,需要的朋友可以参考下日志对于统计排错来说非常有利的.本文总结了nginx日 ...

  9. nginx日志配置指令详解

    这篇文章主要介绍了nginx日志配置指令详解,nginx有一个非常灵活的日志记录模式,每个级别的配置可以有各自独立的访问日志,需要的朋友可以参考下日志对于统计排错来说非常有利的.本文总结了nginx日 ...

随机推荐

  1. BZOJ 2154: Crash的数字表格 [莫比乌斯反演]

    2154: Crash的数字表格 Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 2924  Solved: 1091[Submit][Status][ ...

  2. click与 mousedown

    一.想做出鼠标右键 自己定义的菜单 则需要先使用 document.oncontextmenu= functions(){ event.preventDefault()//去除鼠标右键的默认格式 } ...

  3. 索引超出了数组界限(Microsoft.SqlServer.Smo)

    SSMS连接远程SQL Server服务器是很方便的. 昨天我用SQL Server 2008 SSMS连接SQL Server 2012竟然报错,如下图: 在网上搜了,参考这个参考那个,太啰嗦了,确 ...

  4. WebAPI中无法获取Session对象的解决办法

    在MVC的WebApi中默认是没有开启Session会话支持的.需要在Global中重写Init方法来指定会话需要支持的类型 public override void Init() { PostAut ...

  5. 用 ElementTree 在 Python 中解析 XML

    用 ElementTree 在 Python 中解析 XML 原文: http://eli.thegreenplace.net/2012/03/15/processing-xml-in-python- ...

  6. SQL 基础语法(一)

    SQL 语法 数据库表 一个数据库通常包含一个或多个表.每个表由一个名字标识(例如"客户"或者"订单").表包含带有数据的记录(行). 下面的例子是一个名为 & ...

  7. 页置换算法FIFO、LRU、OPT

    页置换算法FIFO.LRU.OPT 为什么需要页置换 在地址映射过程中,若在页面中发现所要访问的页面不再内存中,则产生缺页中断.当发生缺页中断时操作系统必须在内存选择一个页面将其移出内存,以便为即将调 ...

  8. 关于pc端直播

    写这篇文章首先是想给自己一个总结.整理,还有就是给那些 没有特别明白直播是怎么回事的人一点 思路 最近公司想要做pc端直播,作为一个自认为很菜的前端实在是不知从何下手,所以只能用国人最爱的百度,搜索了 ...

  9. CSS实例练习

    蓝色导航为图片,用background-image实现. 排版用到ul,li标签,下划线运用border-bottom中的dashed,右边文字用到CSS浮动float. 实例: 代码: <!D ...

  10. CUDA[2] Hello,World

    Section 0:Hello,World 这次我们亲自尝试一下如何用粗(CU)大(DA)写程序 CUDA最新版本是7.5,然而即使是最新版本也不兼容VS2015 ...推荐使用VS2012 进入VS ...