资讯专栏INFORMATION COLUMN

Redis 缓存逐出策略

zhonghanwen / 720人阅读

摘要:把当做缓存使用时,有时你可以方便的让它在新数据时自动逐出旧数据。这一点大家都比较清楚,因为默认也会这么干仅支持逐出策略。位系统下默认无限制,位系统则强制指定为当内存使用达到限定值时,可以选择几种不同的策略。则是概率上的逐出老数据。

把 Redis 当做缓存使用时,有时你可以方便的让它在新数据时自动逐出旧数据。这一点大家都比较清楚,因为 memcached 默认也会这么干

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

maxmemory 配置指令

maxmemory 指令用于限定内存使用量。可以在 redis.conf 文件中设置,也可以通过 CONFIG SET 命令在运行时设置。

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

maxmemory 100mb

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

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

逐出策略

具体的逐出策略通过 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 的目的主要还是为了节省内存,对于应用来说,近似与真实,实际上是等效的。

在 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 指令可以方便的设置取样数。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/36199.html

相关文章

  • Redis源码分析】Redis中的LRU算法实现

    摘要:看下边的代码如果配置的是方式,则更新否则按方式更新在的中每次按获取一个值的时候,都会调用函数如果配置使用了模式该函数会更新中的字段为当前秒级别的时间戳方式后文再描述。主要是通过验证的比率,来判断淘汰算法是否有效。 作者:张仕华 LRU是什么 LRU(least recently used)是一种缓存置换算法。即在缓存有限的情况下,如果有新的数据需要加载进缓存,则需要将最不可能被继续访问...

    Keagan 评论0 收藏0
  • 关于Redis热点key的一些思考

    摘要:如何解决针对于热点的解决方案网上的查找出来无非就是两种服务端缓存即将热点数据缓存至服务端的内存中备份热点即将热点随机数,随机分配至其他节点中。伪代码如下生成随机数构造备份新从数据库中取数据存放在中,以便下次能取到代码地址参考文章 关于Redis热点key的一些思考 昨天在和一个已经跳槽的同事聊天时,询问他这段时间面试时碰到的一些问题。自己也想积累一下这方面的知识。其中他说了在面试某赞公...

    wenzi 评论0 收藏0
  • 关于Redis热点key的一些思考

    摘要:如何解决针对于热点的解决方案网上的查找出来无非就是两种服务端缓存即将热点数据缓存至服务端的内存中备份热点即将热点随机数,随机分配至其他节点中。伪代码如下生成随机数构造备份新从数据库中取数据存放在中,以便下次能取到代码地址参考文章 关于Redis热点key的一些思考 昨天在和一个已经跳槽的同事聊天时,询问他这段时间面试时碰到的一些问题。自己也想积累一下这方面的知识。其中他说了在面试某赞公...

    ashe 评论0 收藏0
  • Spring Framework 参考文档(声明式基于注解的缓存

    摘要:声明式基于注解的缓存对于缓存声明,的缓存抽象提供了一组注解触发缓存人口。重新组合要应用于方法的多个缓存操作。虽然在大多数情况下,只声明一个缓存,但是注解允许指定多个名称,以便使用多个缓存。 声明式基于注解的缓存 对于缓存声明,Spring的缓存抽象提供了一组Java注解: @Cacheable:触发缓存人口。 @CacheEvict:触发缓存驱逐。 @CachePut:在不影响...

    makeFoxPlay 评论0 收藏0
  • go实现LRU cache

    摘要:简介概述缓存资源通常比较昂贵通常数据量较大时会竟可能从较少的缓存满足尽可能多访问这里有一种假设通常最近被访问的数据那么它就有可能会被后续继续访问基于这种假设将所有的数据按访问时间进行排序并按驱逐出旧数据那么存在缓存的数据就为热点数据这样既节 1. LRU简介 1.1 概述 缓存资源通常比较昂贵,通常数据量较大时,会竟可能从较少的缓存满足尽可能多访问,这里有一种假设,通常最近被访问的数据...

    Jackwoo 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<