文档章节

如何用Redis做LRU-Cache

沉淀岁月
 沉淀岁月
发布于 2017/09/05 14:41
字数 1604
阅读 16
收藏 1
点赞 0
评论 0

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-randomvolatile-ttl策略和noeviction替换策略一样——不对任何key进行置换。

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

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

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

volatile-lruvolatile-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实现的对比:

lru-compare

测试开始首先在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://blog.csdn.net/cjfeii/article/details/47259519

共有 人打赏支持
沉淀岁月
粉丝 25
博文 257
码字总数 91615
作品 0
朝阳
高级程序员
nginx proxy_store文件管理实现方案

1。源码下载地址: https://github.com/cxwshawn/ngxproxystorefilemgr 2。介绍: 1)、nginx-conf目录:主要实现基于nginx.conf中操作redis数据库代码,基于lua实现;大致流程: 获取cache锁...

shawn chen
2014/12/15
0
0
缓存算法及Redis、Memcached、Guava、Ehcache中的算法

问题导读 1.为什么我们需要缓存? 2.说出几种缓存算法以及它们的作用? 3.什么是什么是缓存? 4.什么是Least Recently User(LRU)? 5.Redis、Memcached使用了哪些缓存算法? 缓存算法 引言 ...

宝塔镇河妖
2015/09/03
0
1
Mybatis缓存机制理解及配置

Ehcache EHCache是来自sourceforge(http://ehcache.sourceforge.net/)的开源项目,也是纯Java实现的简单、快速的Cache组件。EHCache支持内存和磁盘的缓存,支持LRU、LFU和FIFO多种淘汰算法...

Panshuyang
2016/02/23
242
0
由浅入深介绍 Redis LRU 策略的具体实现

原文出处:zxszcaijin 在使用redis作为缓存的场景下,内存淘汰策略决定的redis的内存使用效率。在大部分场景下,我们会采用LRU(Least Recently Used)来作为redis的淘汰策略。本文将由浅入深的...

zxszcaijin
2016/10/27
0
0
TangYuan之Cache的设计

TangYuan之Cache的设计 1. 从Cache的定义开始 在本章节中,我将和大家一起来分析一下TangYuan中Cache的架构设计,我们还是从使用层面开始。在TangYuan中如果我们需要使用Cache功能,我们首先...

xson_org
2016/12/07
373
0
Redis 3.0.0 RC4 发布,无 Redis Cluster 修复

Redis 3.0.0 RC4 发布,此版本是唯一不包括 Redis Cluster bug 修复的 RC 版本!但是此版本并不是稳定版本,因为发现了一个 LRU eviction 算法的 bug。此版本包括关于 redis-cli 方面的新特性...

oschina
2015/02/14
2.5K
5
Redis内存淘汰机制

摘要 Redis是一款优秀的、开源的内存数据库,我在阅读Redis源码实现的过程中,时时刻刻能感受到Redis作者为更好地使用内存而费尽各种心思,例如最明显的是对于同一种数据结构在不同应用场景下...

Float_Luuu
2016/09/03
2.3K
0
redis线上部署规划

一,cpu,内存规划 CPU: CPU不求核数多,但求主频高,Cache大,因为redis主处理模式是单进程的 内存: 一定要设置最大内存maxmemory参数,否则物理内存用爆了就会大量使用Swap 最少预留出55%...

emma_cql
2017/09/08
0
0
Redis 内存淘汰机制

本文作者:伯乐在线 -Float_Lu 。未经作者许可,禁止转载! 欢迎加入伯乐在线专栏作者。 摘要 Redis是一款优秀的、开源的内存数据库,我在阅读Redis源码实现的过程中,时时刻刻能感受到Redis...

伯乐在线
2016/09/03
0
0
Redis新的存储模式diskstore

Redis作者antirez是一个非常勤奋的开发者,在Redis性能已经非常惊人的情况下持续不断开发新的特性,比如从新的cluster源代码看到,作者已经把Dynamo及Paxos一些核心的思想考虑进去并进行了一...

老盖
2011/04/04
1K
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Python PIPEs

https://www.python-course.eu/pipes.php https://www.tutorialspoint.com/python/os_pipe.htm

zungyiu
3分钟前
0
0
gRPC学习笔记

gRPC编程流程 1. proto文件定义 proto文件用于定义需要通过gRPC生成的接口,可以理解为接口定义文档 2. 通过构建工具生成服务基类代码-Maven或Gradle 3. 服务端开发 服务端实现类须实现通过构...

OSC_fly
23分钟前
0
0
Docker Mac (三) Dockerfile 及命令

Dockerfile 最近学习docker的时候,遇到一件怪事,关于docker镜像可能会被破坏,还不知道它会有此措施 所以需要了解构建Dockerfile的正确方法 Dockerfile是由一系列命令和参数构成的脚本,这些命...

___大侠
50分钟前
0
0
Android Studio+NDK+Cmake 移植FFmpeg-4.0.2命令行工具

一、编译 参考大神的帖子,亲测一次编译成功:https://blog.csdn.net/bobcat_kay/article/details/80889398 鉴于以前查文档的经验,这里附上编写例子的时间:2018年7月22日 我用的是ubantu,...

她叫我小渝
50分钟前
0
0
mysql创建数据库

登录MYSQL mysql -u root -p 脚本创建数据库WeChat,并制定默认的字符集是utf8mb4。 CREATE DATABASE Wechat DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_general_ci; 授权 grant all......

niithub
今天
0
0
svn: Unable to connect to a repository URL 的解决方案

错误图示: 解决办法:清除本地保存的授权信息; 1:右键点击本地文件夹,选择设置; TortoiseSVN -> Settings 2:在弹出的对话框中选择 Saved Data, 右侧选择:授权地方清理所有。 然后点确...

宁哥实战课堂
今天
1
0
sleep与wait的区别

Thread.sleep(XXX)方法消耗CPU吗? 这个知识点是我之前认识一直有错误的一个知识点,在我以前的认识里面,我一直认为Thread.sleep(1000)的这一秒钟的时间内,线程的休眠是一直占用着CPU的时间...

码代码的小司机
今天
1
0
20位活跃在Github上的国内技术大牛 leij 何小鹏 亚信

本文列举了20位在Github上非常活跃的国内大牛,看看其中是不是很多熟悉的面孔? 1. lifesinger(玉伯) Github主页: https://github.com/lifesinger 微博:@ 玉伯也叫射雕 玉伯(王保平),...

海博1600
今天
1
0
Mybatis收集配置

一、Mybatis取Clob数据 1、Mapper.xml配置 <resultMap type="com.test.User" id="user"> <result column="id" property="id"/> <result column="json_data" property="jsonData" ......

星痕2018
今天
1
0
centos7设置以多用户模式启动

1、旧版本linux系统修改inittab文件,在新版本执行vi /etc/inittab 会有以下提示 # inittab is no longer used when using systemd. # # ADDING CONFIGURATION HERE WILL HAVE NO EFFECT ON......

haha360
今天
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部