写点什么

什么?我往 Redis 写的数据怎么没了?,java 自学教程百度文库

用户头像
极客good
关注
发布于: 刚刚

1、我往 Redis 里写的数据怎么没了?

使用 Redis 的同学你要明白一点,你为什么用 Redis?用 redis 的作用是什么?用 redis 的好处是什么?凡事多思考一下为什么,多想想背后的原因。


就在不久前有朋友跟我说过,说他们生产环境的 Redis 怎么经常会丢掉一些数据?写进去了,过一会儿可能就没了。我的天啊,你问这个问题就说明 Redis 你就没用对啊。Redis 是缓存,你给当存储了用了是吧?


首先要明白一点啥叫缓存?为啥用缓存?


Redis 是用内存当缓存的。内存是无限的吗?相反,内存是很宝贵而且是有限的,磁盘是廉价而且是大量的。可能一台机器就几十个 G 的内存,但是可以有几个 T 的硬盘空间。Redis 主要是基于内存来进行高性能、高并发的读写操作的。


那既然内存是有限的,比如 Redis 就只能用 10 个 G,你一直往里面写数据,一直写一直写最后 10 个 G 都用的差不多了,你还写会,你想想会发生什么?当然会干掉一些的数据了,然后就保留 10 个 G 的数据。你说会不会造成数据丢失?


那 Redis 会干掉哪些数据?保留哪些数据呢?当然是干掉不常用的数据,保留常用的数据了。


所以说,这是缓存的一个最基本的概念:数据是会过期的。要么是你自己设置个过期时间,要么是 Redis 自己给干掉。


所以你的 Redis 如果使用不当,把生产数据存到里面,又没有去持久化到 mysql,那就会有丢失的可能。

2、我的数据明明都过期了,怎么还占用着内存啊?

还有一种就是如果你给 key 设置好了一个过期时间,你知道到一定的时间再去查这个 key 就没有了,但是你知道 redis 是怎么给你弄成过期的吗?什么时候删除掉?


如果你不知道,在实际的使用过程中你就可能会发现这么一个问题:为啥好多数据明明应该过期了,结果发现 redis 内存占用还是很高?那是因为你不知道 Redis 是怎么删除那些过期 key 的


举例,Redis 内存一共是 10 个 G,你现在往里面写了 5 个 G 的数据,然后你对这些数据全都设置了 10 分钟之后过期,结果 10 分钟之后,你再来查看看,Redis 的内存使用率怎么还是 50%呢?5 个 G 的数据都过期了,我从 redis 里查,是查不到了,结果过期的数据为啥还占用着 Redis 的内存呢。


如果你连这个问题都不知道,上来就懵了,回答不出来,建议你使用 Redis 之前多做做功课,不然你写代码的时候,想当然的认为写进 Redis 的数据就一定会存在,后面导致系统各种漏洞和 bug,就不好弄了。

3、问题剖析

(1)设置过期时间

set key value 过期时间(1小时)表示 set 进去的 key,1 小时之后就没了,就失效了。


【一线大厂Java面试题解析+核心总结学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


我们 set key 的时候,都可以给一个 expire time,就是过期时间,指定这个 key 比如说只能存活 1 个小时?10 分钟?这个很有用,我们自己可以指定缓存到期就失效。


如果假设你设置一批 key 只能存活 1 个小时,那么接下来 1 小时后,redis 是怎么对这批 key 进行删除的?


答案是:定期删除+惰性删除


所谓定期删除,指的是 Redis 默认是每隔 100ms 就随机抽取一些设置了过期时间的 key,检查其是否过期,如果过期就删除。


为什么是随机抽取?假设 Redis 里放了 10 万个 key,都设置了过期时间,你每隔几百毫秒,就检查 10 万个 key,那 redis 基本上就死了,因为这样 cpu 负载会很高的,全都消耗在你的检查过期 key 上了。


所以这里可不是每隔 100ms 就遍历所有的设置过期时间的 key,Redis 如果设置成检查所有 Key 那将是一场性能上的灾难。所以实际上 redis 是每隔 100ms随机抽取一些 key 来检查和删除的。


但是问题是,随机抽取检测 key 是否过去会导致定期删除策略可能会导致很多过期 key 到了时间并没有被删除掉,那咋整呢?所以 Redis 还有另一个策略就是惰性删除


惰性删除?就是说,在你获取某个 key 的时候,Redis 会检查一下 ,这个 key 如果设置了过期时间那么是否过期了?如果过期了此时就会删除,不会给你返回任何东西。


所以并不是 key 到时间就被删除掉,而是你查询这个 key 的时候,Redis 再懒惰的检查一下。


通过上述两种手段,保证过期的 key 一定会被干掉。


那么刚才的问题就不难理解了,就是说,你的过期 key,靠定期删除没有被删除掉,还停留在内存里,占用着你的内存呢,除非你的系统去查一下那个 key,才会被 redis 给删除掉。如果都过期了,定期删除才删了一点点,而你又没有去查,没有触发惰性删除,那么短时间内你的 redis 内存占用率还是会下不来。


但是实际上这还是有问题的,如果定期删除漏掉了很多过期 key,然后你也没及时去查,也就没走惰性删除,此时会怎么样?如果大量过期 key 堆积在内存里,导致 redis 内存块耗尽了,咋整?

用户头像

极客good

关注

还未添加个人签名 2021.03.18 加入

还未添加个人简介

评论

发布
暂无评论
什么?我往Redis写的数据怎么没了?,java自学教程百度文库