如何高效使用Redis作为LRU缓存

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

LRU实际上只是支持驱逐的方式之一。这页包含更多一般的Redis maxmemory指令的话题用于限制内存使用到一个定额,同时它也深入的涵盖了Redis所使用的LRU算法,实际上是精确LRU的近似值。

一、Maxmemory设置指令

Maxmemory设置指令用于配置Redis的数据集使用指定量的内存。可以用redis conf.file设置指令,或者可以在稍晚的时候在运行时间用config set命令。

例如,为了设置内存局限于100百万字节,下列指令可在redis.conf file内使用。设置maxmemory到零使得没有内存限制。这是64位系统的默认行为,而32位系统使用3GB内隐记忆极限。

maxmemory 100mb

当达到指定量的内存后,就可以选择不同的行为,称为策略。Redis可以返回错误的指令,导致使用更多的内存,或者为了每次增加新的数据后返回指定的内存,它可以驱逐一些旧的数据。

二、驱逐策略

当到达maxmemory极限时,使用maxmemory-策略配置指令来执行具体的Redis动作。

以下策略可以使用:

1、noeviction:达到内存限额后返回错误,客户尝试可以导致更多内存使用的命令(大部分写命令,但DEL和一些例外)

2、allkeys-lru:为了给新增加的数据腾出空间,驱逐键先试图移除一部分最近使用较少的(LRC)。

3、volatile-lru:为了给新增加的数据腾出空间,驱逐键先试图移除一部分最近使用较少的(LRC),但只限于过期设置键。

4、allkeys-random: 为了给新增加的数据腾出空间,驱逐任意键。

5、volatile-random: 为了给新增加的数据腾出空间,驱逐任意键,但只限于有过期设置的驱逐键。

6、volatile-ttl: 为了给新增加的数据腾出空间,驱逐键只有秘钥过期设置,并且首先尝试缩短存活时间的驱逐键。

如果没有秘钥去驱逐匹配先决条件,策略volatile-lru, volatile-random 和volatile-ttl行为很像noeviction。

那么根据你应用的访问模式选择正确的驱逐策略是很重要的。然而在应用运行时你可以在运行时间重新设置策略,并且监控缓存缺失的数量并为了调整你的设置点击Redis信息输出。

三、近似LRU算法

Redis的LRU算法不是准确的实现。也就是说Redis没有为逐出选择 最好的候选人 ,也就是没有选择过去最后被访问离现在最久的。反而 是去执行一个 近似LRU的算法,通过抽样少量的key,并且逐出抽样中最后被访问离现在最久的key(最老的访问时间)。

在Redis 3.0(目前的测试版),算法被改进了,使用了一个逐出最佳候选池。改进了算法的性能,使它更加近似真正LRU算法。

算法中,关于逐出检测的样品数量,你可以自己去调整。配置参数是:

maxmemory-samples 5

Redis没有使用真正实现LRU算是的原因是,因为消耗更多的内存。然而对于使用Redis的应用来说,事实上是等价的。下面是Redis的LRU算法和真正LRU算法的比较:

给出配置数量的key生成上面的图表。key从第一行到最后一行被访问,那么第一个key是LRU算法中最好的逐出候选者。之后有50%的key被添加,那么一半的旧key被逐出。

在上图中你可以看见3个明显的区别:

1、浅灰色带是被逐出的对象。

2、灰色带是没有被逐出的对象。

3、绿色带是被添加的对象。

LRU理论实现是在所有的旧key中前一半被逐出。Redis使用的是近似过期的key被逐出。

如你所见,3.0的工作比2.8更好,然而在2.8版本中,大多数最新访问对象的仍然保留。在3.0使用样品为10 时,性能非常接近理论上的LRU算法。

注意:LRU仅仅是一个预测模式,给出的key很可能在未来被访问。此外,如果你的数据访问模式类似于幂律(线性的),大多数key都可能被访问那么这个LRU算法的处理就是非常好的。

在实战中 ,我们发现使用幂律(线性的)的访问模式,在真正的LRU算法和Redis的LRU算法之间差异很小或者不存在差异。

你可以提升样品大小配置到10,它将接近真正的LRU算法,并且有不同错过率,但是要消耗更多的CPU。

在调试时使用不同的样品大小去调试非常简单,使用命令CONFIG SET maxmemory-samples 实现。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Mybatis-plus基于redis实现二级缓存过程解析

    1. mybatis-plus开启二级缓存 spring: datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.jdbc.Driver jdbc-url: jdbc:mysql://192.168.222.155:3306/sys?serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true&

  • SpringBoot2整合Redis缓存三步骤代码详解

    遵循SpringBoot三板斧 第一步加依赖 <!-- Redis --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> <!-- redis依赖commons-pool 这个依赖一定要添加 --> <

  • mybatis plus使用redis作为二级缓存的方法

    建议缓存放到 service 层,你可以自定义自己的 BaseServiceImpl 重写注解父类方法,继承自己的实现.为了方便,这里我们将缓存放到mapper层.mybatis-plus整合redis作为二级缓存与mybatis整合redis略有不同. 1. mybatis-plus开启二级缓存 mybatis-plus.configuration.cache-enabled=true 2. 定义RedisTemplate的bean交给spring管理,这里为了能将对象直接存取到redis中,

  • Redis缓存常用4种策略原理详解

    我们都知道,提高系统性能的最简单也最流行的方法之一其实就是使用缓存.我们引入缓存,相当于对数据进行了复制.每当系统数据更新时,保持缓存和数据源(如 MySQL 数据库)同步至关重要,当然,这也取决于系统本身的要求,看系统是否允许一定的数据延迟. 最常见的几种缓存策略.它们的优缺点以及使用场景,分别是: Cache-Aside Read-Through Write-Through Write-Behind Cache-Aside 策略 Cache-Aside可能是最常用的缓存策略.在这种策略下,应

  • java操作Redis缓存设置过期时间的方法

    关于Redis的概念和应用本文就不再详解了,说一下怎么在java应用中设置过期时间. 在应用中我们会需要使用redis设置过期时间,比如单点登录中我们需要随机生成一个token作为key,将用户的信息转为json串作为value保存在redis中,通常做法是: //生成token String token = UUID.randomUUID().toString(); //把用户信息写入redis jedisClient.set(REDIS_USER_SESSION_KEY + ":"

  • Redis缓存穿透出现原因及解决方案

    在并发式的项目当中,一定要考虑一个缓存穿透的情况.那么什么是缓存穿透呢?简单的说来,就是当大量请求的key根本不在缓存当中,所以导致了请求直接到了数据库上,根本没有经过缓存这一层.比如一个黑客故意制造我们缓存中不存在的key发送大量的请求,就会导致请求直接落到数据库上. 也就是说,缓存穿透就是:1.缓存层不命中.2,存储层不命中,不将空的结果写回缓存.3,返回空结果给客户端. 一般mysql的默认最大连接数是150左右,当然这个是可以用show variables like '%max_conn

  • Spring Cache手动清理Redis缓存

    这篇文章主要介绍了Spring Cache手动清理Redis缓存,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 注册cacheRedisTemplate 将 cache 的 RedisTemplate 注册为Bean @Bean(name = "cacheRedisTemplate") public RedisTemplate cacheRedisTemplate(@Qualifier("jedisConnectionFac

  • SpringBoot Redis缓存数据实现解析

    这篇文章主要介绍了SpringBoot Redis缓存数据实现解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.启用对缓存的支持 spring对缓存的支持有两种方式: a.注解驱动的缓存 b.XML声明的缓存 本文主要介绍纯Java配置的缓存,那么必须在配置类上添加@EnableCaching,这样的话就能启动注解驱动的缓存. 2.使用Redis缓存 缓存的条目不过是一个键值对(Key-Value),其中key描述了产生value的操作和

  • 如何高效使用Redis作为LRU缓存

    当用Redis作为一个LRU存储时,有些时候是比较方便的,在你增添新的数据时会自动驱逐旧的数据.这种行为在开发者论坛是非常有名的,因为这是流行的memcached系统的默认行为. LRU实际上只是支持驱逐的方式之一.这页包含更多一般的Redis maxmemory指令的话题用于限制内存使用到一个定额,同时它也深入的涵盖了Redis所使用的LRU算法,实际上是精确LRU的近似值. 一.Maxmemory设置指令 Maxmemory设置指令用于配置Redis的数据集使用指定量的内存.可以用redis

  • 手动实现Redis的LRU缓存机制示例详解

    前言 最近在逛博客的时候看到了有关Redis方面的面试题,其中提到了Redis在内存达到最大限制的时候会使用LRU等淘汰机制,然后找了这方面的一些资料与大家分享一下. LRU总体大概是这样的,最近使用的放在前面,最近没用的放在后面,如果来了一个新的数,此时内存满了,就需要把旧的数淘汰,那为了方便移动数据,肯定就得使用链表类似的数据结构,再加上要判断这条数据是不是最新的或者最旧的那么应该也要使用hashmap等key-value形式的数据结构. 第一种实现(使用LinkedHashMap) pub

  • Java手动实现Redis的LRU缓存机制

    前言 最近在逛博客的时候看到了有关Redis方面的面试题,其中提到了Redis在内存达到最大限制的时候会使用LRU等淘汰机制,然后找了这方面的一些资料与大家分享一下. LRU总体大概是这样的,最近使用的放在前面,最近没用的放在后面,如果来了一个新的数,此时内存满了,就需要把旧的数淘汰,那为了方便移动数据,肯定就得使用链表类似的数据结构,再加上要判断这条数据是不是最新的或者最旧的那么应该也要使用hashmap等key-value形式的数据结构. 第一种实现(使用LinkedHashMap) pub

  • 浅谈java如何实现Redis的LRU缓存机制

    目录 LRU概述 使用LinkedHashMap实现 使用LinkedHashMap简单方法实现 双链表+hashmap LRU概述 最近使用的放在前面,最近没用的放在后面,如果来了一个新的数,此时内存满了,就需要把旧的数淘汰,那为了方便移动数据,肯定就得使用链表类似的数据结构,再加上要判断这条数据是不是最新的或者最旧的那么应该也要使用hashmap等key-value形式的数据结构. 使用LinkedHashMap实现 package thread; import java.util.Link

  • Java实现LRU缓存的实例详解

    Java实现LRU缓存的实例详解 1.Cache Cache对于代码系统的加速与优化具有极大的作用,对于码农来说是一个很熟悉的概念.可以说,你在内存中new 了一个一段空间(比方说数组,list)存放一些冗余的结果数据,并利用这些数据完成了以空间换时间的优化目的,你就已经使用了cache. 有服务级的缓存框架,如memcache,Redis等.其实,很多时候,我们在自己同一个服务内,或者单个进程内也需要缓存,例如,lucene就对搜索做了缓存,而无须依赖外界.那么,我们如何实现我们自己的缓存?还

  • Redis中LRU淘汰策略的深入分析

    前言 Redis作为缓存使用时,一些场景下要考虑内存的空间消耗问题.Redis会删除过期键以释放空间,过期键的删除策略有两种: 惰性删除:每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键:如果没有过期,就返回该键. 定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面的过期键. 另外,Redis也可以开启LRU功能来自动淘汰一些键值对. LRU算法 当需要从缓存中淘汰数据时,我们希望能淘汰那些将来不可能再被使用的数据,保留那些将来还会频繁访问的数据,但最大的问题是

  • Java实现简单LRU缓存机制的方法

    一.什么是 LRU 算法 就是一种缓存淘汰策略. 计算机的缓存容量有限,如果缓存满了就要删除一些内容,给新内容腾位置.但问题是,删除哪些内容呢?我们肯定希望删掉哪些没什么用的缓存,而把有用的数据继续留在缓存里,方便之后继续使用. LRU是Least Recently Used的缩写,即最近最少使用,是一种常用的页面置换算法,选择最近最久未使用的页面予以淘汰. 二.LRU的使用 LRUCache cache = new LRUCache( 2 /* 缓存容量 */ ); cache.put(1,

  • Redis不仅仅是缓存,还是……

    你需要一个经典数据库吗? 一段时间以来,巨大数量的数据处理迫使所有的应用程序在数据库层前添加缓存策略.即使经典数据库进行了大量的下划线优化,仍然不能提供足够的速度和可用性.主要原因在于数据存储越远,获取数据就越困难.另一个原因是因为数据库中的数据通常保存在磁盘中,而不是在内存.经典数据库却是在内存上嵌入了缓存来优化,但是拥有一个专用的独立缓存也是一种很常用的策略. 在解决访问数据库的性能问题,通常的解决方案是缓存.缓存并不新鲜,缓存实际上是把经常访问的少量数据保存在离你更近的地方.我们在处理器上

  • 彻底弄懂Redis的LRU淘汰策略

    目录 Redis的淘汰策略 LRU算法简介 实现思想推导 巧用LinkedHashMap 手写LRU 第一步:构建DoubleLinkedList对象 第二步:构建节点 第三步:初始化DoubleLinkedList对象 第四步:LRU对象属性 第五步:LRU对象的方法 第六步:测试 总结 今天我们这篇文章的目的是要 搞懂LRU淘汰策略 以及 实现一个LRU算法 . 文章会结合图解循序渐进的讲解,跟着我的思路慢慢来就能看懂,我们开始吧. 文章导读 Redis的淘汰策略 为什么要有淘汰策略呢? 因

  • 利用Redis进行数据缓存的项目实践

    目录 1. 引言 2. 将信息添加到缓存的业务流程 3. 实现代码 3.1 代码实现(信息添加到缓存中) 3.2 缓存更新策略 3.3 实现主动更新 4. 缓存穿透 4.1 解决缓存穿透(使用空对象进行解决) 5. 缓存雪崩 6. 缓存击穿 6.1 互斥锁代码 6.2 逻辑过期实现 1. 引言 缓存有啥用? 降低对数据库的请求,减轻服务器压力 提高了读写效率 缓存有啥缺点? 如何保证数据库与缓存的数据一致性问题? 维护缓存代码 搭建缓存一般是以集群的形式进行搭建,需要运维的成本 2. 将信息添加

随机推荐