首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >redis淘汰+过期双向保证高可用 | redis 为什么那么快?

redis淘汰+过期双向保证高可用 | redis 为什么那么快?

作者头像
Java_老男孩
发布于 2021-07-01 02:03:04
发布于 2021-07-01 02:03:04
73400
代码可运行
举报
运行总次数:0
代码可运行

前言

redis和数据相比除了他们的结构型颠覆以外!还有他们存储位置也是不相同。传统数据库数据存储在硬盘上每次数据操作都需要IORedis是将数据存储在内存上的。这里稍微解释下IO是啥意思。IO就是输入流输出流方式将数据在硬盘和内存之间进行交互!而redis直接在内存上就剩下了IO操作。这也是redis快的原因之一吧

  • 内存相对于硬盘来说很宝贵。我们平时的电脑也是硬盘是内存的几百倍。既然内存很宝贵而redis又将数据存储在内存上那么redis肯定不能肆无忌惮的进行存储 。这就需要redis和开发者们作出相应的优化
  • 首先redis在配置文件(redis.conf)中通过maxmemory参数指定redis 设置整个对内存的支配大小!
  • 其次就是要求我们开发者在想redis中填值的时候根据自己的需求设置相应的key过期时间。这样不必要的数据就会被redis过期驱逐策略清除。从而节省内存供别人使用

本文凌驾于redis基础之上,这里笔者默认大家都已经安装了redis . 并实际使用过redis

内存分配

  • maxmemory 指定大小。在redis.conf配置文件中可以直接指定。他的单位时byte。
  • 上图中注释部分是给大家的解释,实际中#配置需要换行哈!!!友情提示
  • 另外我们可以连接上redis通过config命令来设置
  • 两种方式都可以设置,前者是全局设置重启之后仍然有效!后者是临时设置重启之后就会重新加载redis.conf中的配置。

键过期

  • 上面我们从redis本身角度出发设置了内存限制,这样不用担心他们吞噬系统内存!下面就需要我们开发者设计角度约束自己了。

设置过期时间

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
expire key time
  • 设置过期时间默认单位时S 。
  • 然后通过ttl 命令可以查看剩余过期时间
  • 经过多次执行ttl能够观察到剩余时间在不断的减少!当减少到0的时候就被给驱逐策略驱逐!注意这里说的是驱逐策略驱逐并不是意味着立马被删除

更新过期时间

  • del key 直接将key删除了那么该key对应的过期自然也就不存在了!这种情况笔者也算作是更新过期时间
  • set getset等命令重新设置key、value方式会覆盖过期时间 , 直接被覆盖成-1
  • setgetset包括del严格意义是覆盖过期时间。真正做到更新过期时间的还是expire .在expire是以最新为准的!
  • 上面其实都修改了key才会引发原本的过期时间失效的!因为此key非彼key 。 但是appendincr 等命令是改变值这种命令是不会影响到原来的过期设置的

淘汰策略

  • 根据上面配置我们可以将我们的redis最大内存设置为1MB , 设置大小随便最好能小点。然后我们通过Java小程序不断向redis中填充。最终当内存不够使用时就会报错
  • 报错就是因为内存满了,新增的key被redis拒绝了!不仅仅是新增的被拒绝,就算此时我们想改变已经在redis中的key的值也是不可用的
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void main(String[] args) {
    Jedis jedis = new Jedis("39.102.60.114", 6379);
    jedis.auth("Qq025025");
    Integer index = 1;
    while (true) {
        String uuid = UUID.randomUUID().toString();
        jedis.set(index.toString(), uuid);
        System.out.println(index++);
    }
}
  • 不管是append 还是set 都是报OOM command not allowed when used memory > maxmemory 。代码中打印和redis键个数一致;说明我们默认的淘汰策略是直接拒绝
  • 总结下来就是:当redis内存被使用满了后,任何的写操作都会被拒绝!
  • 当没有足够内存时难道就这么直接拒绝吗?上面也提到了需要我们程序员自己根据需求设置键过期已释放内存供其他有需要的key使用!那么设置了过期key之后这些key又是怎么被清除的呢? 这就牵扯出我们的淘汰策略

volatile-lru【最近很少使用】

当内存告警时redis会将近期很少使用且设置了过期时间的key剔除出去,即使该key还没有到过期时间。如果没有符合的key也就是执行之后内存仍然不足时将会和默认淘汰策略noeviction抛出一样的错误OOM command not allowed when used memory > maxmemory

  • 首先我们在redis.conf中配置我们最近很少使用策略. maxmemory-policy volatile-lru 。 然后重启我们的redis服务 。重启之后flushall清空所有数据,我们在通过上面的Java程序重新生成下数据!
  • Java程序中我们设置前100个key添加过期时间
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public static void main(String[] args) {
    Jedis jedis = new Jedis("39.102.60.114", 6379);
    jedis.auth("Qq025025");
    Integer index = 1;
    while (true) {
        String uuid = UUID.randomUUID().toString();
        if (index < 100) {
            jedis.setex(index.toString(),360, uuid);
        } else {
            jedis.set(index.toString(), uuid);
        }
        System.out.println(index++);
    }
}
  • 简单分析下为什么程序计数器大于redis库中的key数量!就是因为我们为前100设置了过期时间。当内存不足时redis就会将当前设置了过期时间的key中最近最少使用的key进行剔除!所以我们计数器会大于键数量。因为有部分键被清除了!我们获取前100的key都是null , 说明被删除了! 那么为什么本次计数器不是比上次多100 。 那是因为我们每次存储进来的是uuid, 所占长度都不是固定的。还有本身淘汰策略也是占用内存的

策略总结

  • 上面演示了最近最少使用的淘汰策略!除此之外还有其他的策略
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
noeviction:拒绝写请求,正常提供读请求,这样可以保证已有数据不会丢失(默认策略);
2\. volatile-lru:尝试淘汰设置了过期时间的key,虽少使用的key被淘汰,没有设置过期时间的key不会淘汰;
3\. volatile-ttl:跟volatile-lru几乎一样,但是他是使用的key的ttl值进行比较,最先淘汰ttl最小的key;
4\. volatile-random:其他同上,唯一就是他通过很随意的方式随机选择淘汰key集合中的key;
5\. allkeys-lru:区别于volatile-lru的地方就是淘汰目标是全部key,没设置过期时间的key也不能幸免;
6\. allkeys-random:这种方式同上,随机的淘汰所有的key。
  • 使用哪种淘汰策略需要我们结合自己的项目场景来配合使用!!!

过期删除

  • 上面我们从【键过期】、【淘汰策略】两个角度分析了redis 。 仅仅这两方面还没有完全高效使用内存!淘汰策略是濒临内存不足时触发。那么当设置了过期时间的键真正到了过期时间而此时内存尚够使用?这种场景是不是需要将过期键删除呢?
  • 因为redis是单线程,那么在键过期的时候如何不影响对外服务的同时清除过期键呢?答案是【不行】。严格意义是无法解决的因为单线程同时只能做一件事!既然无法解决那么我们可以达到一种协调状态!如果同一时刻出现一个过期键那么清除键很快这时候阻塞外部服务的时间很短可能毫秒级设置纳秒级!
  • 但是如何同一时间发生上万键过期,如果想要删除上万键那肯定需要花费一定时间这时候就会阻塞对外服务!这肯定是不能接受的,阻塞时间过长会导致客户端连接超时报错的。这在并发场景下更是无法接受的!所以redis如何应对同一时间过多数据过期的场景,他的删除过期键的方法略有不同!

定时清除

  • 针对每个过期键设置一个定时器,在过期时就会进行清理该键!
  • 该做法能够做到数据实时被清理从而保证内存不会被长期占用!提高了内存的使用率!
  • 但是问题也随之而来,每一个key需要设置一个定时器进行跟踪。redis这里笔者猜测应该是启用另外线程来进行定时跟踪!这里有清除的还请帮忙解答下?
  • 当同一时间过期key很多的时候!我们的CPU就需要不断的执行这些定时器从而导致CPU资源紧张。最终会影响到redis服务的性能

定期清除

  • 定期删除就是上面我们图示效果,redis会每隔100ms执行一次定时器,定时器的任务就是随机抽取20个设置过期的key 。 判断是否进行清除。上面图示中说明中写错了不是10S , 而是每隔100ms 。请原谅我的粗心!!!
  • 定期删除和定时删除作用是相反的!定期删除是将key集中进行处理同时为了保证服务的高可用在处理时加入的时间限制。每次执行总时长不能超过25ms 。 也就是说对于客户端来说服务端的延迟不会超过25ms
  • 他的优点就是不需要CPU频繁的进行操作key清除!因为他是定期进行清除所以就会导致一部分数据没有来得及清除从而导致内存使用上会被一直占用!

惰性清除

  • 关于惰性删除我们在平时开发中也经常使用这种方式!当数据过期时redis并不急着去清除这些数据,而是等到该key被再次请求时进行删除!这样在最终效果上是没有问题的。
  • 优点和定期清除一样他保证了CPU不必频繁的进行切换!但是缺点也很明显会导致很多已经过期的key仍然在redis中。

惰性清除+定期清除

  • 我们开头说过了既要高可用又要实时清理过期key 这是无法做到的!既然无法做到我们就需要在CPU和内存中间做一个权衡!redis内部是使用惰性清除和定期清除两种方式结合使用,最终保证CPU和内存之间的一种平衡!

总结

  • 相信大家对上面三个概念有点模糊了。【键过期】、【淘汰策略】、【过期清除】
  • 首先【键过期】是redis给我们开发者提供的功能。我们可以根据自己的业务需求合理的设置键的过期时间,从而保证内存的高可用
  • 其次【过期清除】在我们之前设置的过期的key如何进行合理的清除,并不能一股脑一下子进行清除因为数据过大会导致服务的卡顿。这个时候我们需要通过定期清除减缓清除key代码的卡顿。在redis.conf中我们可以设置 hz 10 代表1S中平均执行几次这也是我们上面所说的100MS的由来。但是仅仅定期删除会产生遗漏数据所以我们还需要加上惰性清除,最终保证对客户端来说数据是准确实时清除的。
  • 那么关于【淘汰策略】又是啥呢?在上面过期清除是如果用户一直不请求过期的key ,并且随着业务产生越来越多的过期key . 这时候redis服务中还会堆积很多过期的无效key 。这个时候如果内存不够用了的话那又该怎么办呢?这时候我们需要设置淘汰策略比如果volatile-lru . 就会将最近最少使用的设置过期key进行清除从而保证尽可能的接收更多的有效数据!
  • 这就是为什么会设计三者的原因!好好理解上面三个主题我们再去想想为什么会发生【缓存雪崩】、【缓存崩溃】、【缓存击穿】就好理解一点了呢?
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Redis之过期key的淘汰及缓存淘汰策略解读
我们都知道在Redis 所有的数据结构都可以设置过期时间,时间一到,就会自动删除。想象一下里面有一个专门删除过期数据的线程,如果数据已过期就立马删除。这个时候可以思考一下,会不会因为同一时间太多的 key 过期,以至于线程忙不过来。同时因为 Redis 是单线程的,删除的时间也会占用线程的处理时间,如果删除的太过于繁忙,会不会导致线上读写指令出现卡顿。
一个风轻云淡
2023/10/15
3700
面试必问:redis过期key删除和内存淘汰策略
众所周知,Redis是一种内存级kv数据库,所有的操作都是在内存里面进行,定期通过异步操作把数据库数据flush到硬盘上进行保存。因此它是纯内存操作,Redis的性能非常出色,每秒可以处理超过10万次读写操作。虽然是内存数据库,但是其数据可以持久化,而且支持丰富的数据类型。
高性能架构探索
2022/08/25
5210
面试必问:redis过期key删除和内存淘汰策略
Redis内存淘汰和过期删除策略原理分析
Redis是一个内存键值对数据库,所以对于内存的管理尤为重要。Redis内部对于内存的管理主要包含两个方向,过期删除策略和数据淘汰策略。 思考:
政采云前端团队
2023/10/25
5390
Redis内存淘汰和过期删除策略原理分析
Redis键过期策略、内存淘汰策略详解
除了string独有设置过期时间的方法,其他类型都需要依靠expire方法设置时间,若:
JavaEdge
2022/11/30
1.2K0
Redis键过期策略、内存淘汰策略详解
Redis的过期策略以及内存淘汰机制
其实,redis采用的是定期删除+惰性删除策略。 为什么不用定时删除策略? 定时删除,用一个定时器来负责监视key,过期则自动删除。虽然内存及时释放,但是十分消耗CPU资源。在大并发请求下,CPU
traffic
2020/04/09
1.1K0
Redis的过期策略&内存淘汰策略
Redis作为当下最受欢迎的NoSQL数据库之一,在很多场景下都会使用到;Redis的存储分为内存存储、磁盘存储和log文件三部分,重启后,Redis可以从磁盘重新将数据加载到内存中,这些可以通过配置文件对其进行配置,正因为这样,Redis才能实现持久化
Kevinello
2022/08/19
9160
Redis的过期策略&内存淘汰策略
面试官:聊一聊Redis过期淘汰策略
Redis 是一个开源的使用ANSI C编写、遵守BSD协议、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。
做棵大树
2024/04/09
7690
Redis过期--淘汰机制的解析和内存占用过高的解决方案
Redis在我们平时的开发或者练习的时候,往往很容易忽略一个问题,那就是我们的Redis内存占满的问题。但是在真是的商业开发中,Redis的实际占满是真正会存在这样的问题的。那么如果Redis在某一刻占满内存,我们又没有对它进行相应的设置它会出现什么情况呢?会不会导致我们整个因为使用Redis而整个业务垮掉?
码农编程进阶笔记
2021/07/20
6550
Redis的过期策略和内存淘汰策略最全总结与分析
提到内存管理,我们就需要考虑Redis的内存过期策略和内存淘汰机制。该文章便从这两方面入手,分享一些在Redis内存方面相关的基础知识。
兔云小新LM
2020/07/06
1.9K0
Redis的过期策略和内存淘汰策略最全总结与分析
Redis-内存回收
  Reids 所有的数据都是存储在内存中的,在某些情况下需要对占用的内存空间进行回收。内存回收主要分为两类,一类是 key 过期,一类是内存使用达到上限(max_memory)
会说话的丶猫
2020/10/27
1.3K0
Redis-内存回收
Redis详解(十一)------ 过期删除策略和内存淘汰策略
  ②、设置完一个键的过期时间后,到了这个时间,这个键还能获取到么?假如获取不到那这个键还占据着内存吗?
IT可乐
2020/06/02
1.6K0
Redis详解(十一)------ 过期删除策略和内存淘汰策略
Redis过期键删除策略及淘汰策略
  Redis的所有键都可以设置过期策略,Redis的每个设置了过期时间的key都会被放在一个独立的字典中,用于遍历删除。
用户7353950
2022/05/10
6110
Redis过期策略以及淘汰机制
Redis中可以通过expire设置键的过期,那么Redis又是什么时候删除键的呢?
用户7386338
2020/10/10
5530
理解Redis的内存回收机制和过期淘汰策略
前言 我们知道Redis是分布式缓存中间件,它是基于内存运行,可是有没有想过比较好的服务器内存也不过几十G,能存多少数据呢,当内存占用满了之后该怎么办呢?需要存储新的数据到缓存中该如何办?就这些问题,
黎明大大
2021/03/08
1.7K0
Redis淘汰删除策略
Redis数据库作为缓存系统使用通常只保留部分的热点数据。当热点数据超过Redis设置的内存总大小时就需要删除陈旧的数据,为键空间设计一套高效的过期策略将使得应用程序的内存需求更可控。本文介绍Redis的键淘汰策略以及在Redis内部是如何实现的。
一生何求
2019/12/21
1.5K0
Redis过期策略以及内存淘汰机制
如果你的 Redis 只能存10G数据,你写了12G,那么 Redis 会怎么淘汰那2G数据呢?
ITer.996
2019/12/15
7090
Redis的过期删除策略和内存淘汰机制
在设置key的过期时间的同时,为该key创建一个定时器,让定时器在key的过期时间来临时对key进行删除。 优点: 保证内存被尽快释放。 缺点: 1)若过期key很多,删除这些key会占用很多的CPU时间,在CPU时间紧张的情况下,CPU不能把所有的时间用来做要紧的事儿,还需要去花时间删除这些key。 2)定时器的创建耗时,若为每一个设置过期时间的key创建一个定时器(将会有大量的定时器产生),性能影响严重。
范蠡
2020/12/15
1K0
Redis的过期策略和内存淘汰策略配置说明
一旦内存使用达到上限,Redis会根据选定的回收策略(参见:maxmemmory-policy)删除key
兔云小新LM
2019/12/05
2.1K0
Redis的过期策略和内存淘汰策略配置说明
Redis6.0.6的三大内存过期策略和八大淘汰策略
Redis在我们日常开发中是经常用到的,Redis也是功能非常强大,可以进行缓存,还会有一些排行榜、点赞、消息队列、购物车等等;当然还有分布式锁Redisson,我们使用肯定少不了集群!小编最近学习到一些内存如果满了Redis是怎么操作呢?肯定像我们JVM一样,有回收或者淘汰的机制!今天小编和大家一起学习一下,小编也是看了阳哥的课,觉得讲的很好,记录一下,希望可以帮助到大家!!
掉发的小王
2022/07/11
4480
Redis过期策略和内存淘汰机制
Redis缓存作为提高系统性能最好的方式相信大家对其一定不陌生,各位作为秃头老码农不仅需要掌握Redis的基础用法还得了解Redis的相关原理,比如Redis过期策略和内存淘汰机制。
JAVA日知录
2020/08/17
6510
相关推荐
Redis之过期key的淘汰及缓存淘汰策略解读
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档