转载:善待Redis中的数据
Redis是我们数据的保管者,我们可以随时存随时取,大的小的,重要的不重要的,它都毫无怨言的帮我们保存着,甚至有些时候,我们变得很懒,存东西进去的时候顺便还贴张纸:“过了一个星期就帮我扔了吧”,对于这些,Redis也都默默的接受了(谁叫Antirez把redis设计的这么好呢)。
这次要写的就是关于这张留言纸的事。
- 主动过期: Redis对数据是惰性过期,当一个key到了过期时间,Redis也不会马上清理,但如果这个key过期后被再次访问,Redis就会主动将它清理掉。
- 被动过期: 如果过期的Key一直没被访问,Redis也不会一直把它放那不管,它会每秒10次的执行以下的清理工作:
- 随机从所有带有过期时间的Key里取出20个
- 如果发现有过期的,就清理
- 如果这里有25%的Key都是过期的,就继续回到第一步再来一次
这套过期机制设计的很赞,可以这样理解:如果当前有超过1/4的Key是过期的话,就不停地清理,直到只剩下1/4不到的Key是要过期的为止,然后就慢慢地随机抽查着清理。
现在我们再说说对待Redis数据的姿势问题。
先看一个现象,某段程序每天24小时的跑着,但时不时地出现拿不到连接的错误:
Caused by: redis.clients.jedis.exceptions.JedisConnectionException: Could not get a resource from the pool
...
Caused by: java.util.NoSuchElementException: Unable to validate object
这个错误是因为 JedisPool拿到一个连接后,调用jedis.ping()方法没有得到正确的返回『pong』消息,而出现这个问题时,并不是traffic的高峰期,redis的cpu不高,于是程序员很快就怀疑到网络上,难道有”丢包”?
但跑了几天,发现出错的时间固定在某几个时间点(如晚上9点~10点),莫非是扫地阿姨每天定时在机房打扫卫生,碰着网线了?(有时候不得不佩服程序员的想象力)
然而在一个夜黑风高的晚上,程序员的脑子在这个时候一般是最清醒的,这时告警短信又来了,打开redis监控,像在唯品会上逛街一样,对着redis的各项监控数据逛啊逛,突然,看到有几条Expires的数据,当时的表情只能用看到关注了几天的商品上标了大大”0.1折”时的表情来形容。
接下来的事情,想必大家也都猜到个七七八八了,当然是下单抢购支付了,脑子里一系列的运算,掐指一算: 『这个时间点正好有一大批key过期』,而且都是大的Set集合,每个都有几十万的数据,再一算: 『Redis里的大部分需要过期的key就是这些key』。
于是,答案有了,Redis进行被动过期清理时,发现怎么随机,都有超过1/4的Key都是过期的,就忙着不停的删啊删,再加上又都是大集合的删除,O(N)的操作复杂度,无奈,等redis删完时,客户端那边的命令都等超时了。
***
原因找到了,如何解决?看业务场景吧,对于我们的场景,做法是将过期时间设长一点,然后把这些可以删掉的Key标记一下,丢到一个后台线程那里分页删Set里的数据,这样就算redis再做过期操作,也不会用太多的时间来删除。
最后,稍稍总结下,对于大个的集合对象,放redis的时候需要额外注意,如果想依赖redis的过期,可能会造成过期时短暂的redis block。
所以,要善待redis数据,比如不用了就自己清理掉,不要等着redis来帮你。
还有,就是, 设置expire的时候, 加个随机值.. 比如大家的过期时间都是3600就不好了, 如果设置成 3600+rand(0,100) 就会把这些key的过期时间分散开来... 当然, 只有部分场景是需要这么做的~
转载:善待Redis中的数据的更多相关文章
- 读取redis中的数据时出现:MISCONF Redis is configured to save RDB snapshots
读取redis中的数据时出现:MISCONF Redis is configured to save RDB snapshots 以下为异常详细信息: Exception in thread &q ...
- 往redis中存储数据是利用pipeline方法
在redis中保存数据时,保存和设置有效时间是分开写的话,如果中间出现的异常,这会导致数据永久有效,因此就可以采用pipeline方法. # 创建redis管道对象,可以一次执行多个语句 pipeli ...
- 如何将redis中的数据导入到本地MongoDB和MySQL数据库
将redis中的数据导入到本地MongoDB数据库 创建一个process_items_mongodb.py文件(文件名自定义): #!/usr/bin/env python # -*- coding ...
- 多线程查询数据,将结果存入到redis中,最后批量从redis中取数据批量插入数据库中【我】
多线程查询数据,将结果存入到redis中,最后批量从redis中取数据批量插入数据库中 package com.xxx.xx.reve.service; import java.util.ArrayL ...
- Redis 中的数据持久化策略(RDB)
Redis 是一个内存数据库,所有的数据都直接保存在内存中,那么,一旦 Redis 进程异常退出,或服务器本身异常宕机,我们存储在 Redis 中的数据就凭空消失,再也找不到了. Redis 作为一个 ...
- 善待Redis里的数据--Unable to validate object
又是一篇关于姿势的文章,为什么是”又”呢?因为上个星期刚写完一篇关于Apache Commons Pool的正确使用姿势的文章,点击此处阅读. Redis为我们提供便利的同时,我们也要善待里面的数据 ...
- Redis中的数据对象
redis对象 redis中有五种常用对象 我们所说的对象的类型大多是值的类型,键的类型大多是字符串对象,值得类型大概有以下几种,但是无论哪种都是基于redisObject实现的 redisObjec ...
- Redis 中的数据持久化策略(AOF)
上一篇文章,我们讲的是 Redis 的一种基于内存快照的持久化存储策略 RDB,本质上他就是让 redis fork 出一个子进程遍历我们所有数据库中的字典,进行磁盘文件的写入. 但其实这种方式是有缺 ...
- java 向Redis中存放数据 List<Device>转String
/** * redis服务 */ @Autowired private RedisService redisService; //创建 Device 对象 Device no = new Devic ...
随机推荐
- 解决github访问问题
github这是个好地方.但是,上不去就蛋疼. 今天github上不去,果断f12下,看下network.发现里面好多请求都是指向 github.global.ssl.fastly.net这个域名的, ...
- C# DateTime结构的常用方法
在项目开发中,经常会碰到日期处理.比如查询中,可能会经常遇到按时间段查询,有时会默认取出一个月的数据.当我们提交数据时,会需要记录当前日期,等等.下面就看看一些常用的方法. 首先,DateTime是一 ...
- Nginx模块开发入门(转)
前言 Nginx是当前最流行的HTTP Server之一,根据W3Techs的统计,目前世界排名(根据Alexa)前100万的网站中,Nginx的占有率为6.8%.与Apache相比,Nginx在高并 ...
- 房费制VB版本(一个)——系统分析
首先.我们先回答两个个问题: 1.机房收费系统"是什么"? 2.机房收费系统应该"干什么"? 我的回答 ...
- java 正则表达式提取html纯文本
本文来自我的个人博客: java 正则表达式提取html纯文本 做内容的大家都知道,从html中直接提取纯文本是一个非常大的问题.现将我做的正则匹配贴上: import java.util.regex ...
- JavaEE(19) - Web层和EJB的整合(Session Bean)
1. 通过依赖注入访问无状态Session Bean #1. EJB注入Servlet中 #2. EJB注入JSF中 2. 通过EJB引用访问有状态Session Bean 3. 在工具类中访问Ses ...
- tc-SRM-626-DIV1-250
枚举alice投掷骰子得到的结果的每一种情况极其数量. 枚举bob投掷骰子得到的结果的每一种情况极其数量. 然后枚举alice投掷骰子得到的结果的数量和bob投掷骰子比alice低的数量. 然后计算结 ...
- Android开发之自己主动登录功能的实现
在我们平时使用的手机应用都能够实现仅仅须要登陆一次账号后,第二次进入应用直接跳转到效果界面的效果,还有QQ的登陆框是怎样记忆我们的隐身登陆,保存账号选项的呢,这些都是通过使用SharedPrefere ...
- MySQL中游标使用以及读取文本数据
原文:MySQL中游标使用以及读取文本数据 前言 之前一直没有接触数据库的学习,只是本科时候修了一本数据库基本知识的课.当时只对C++感兴趣,天真的认为其它的课都没有用,数据库也是半懂不懂,胡乱就考试 ...
- 删RAC中间ASM和LISTENER
资源的正确方法
在我们的安装RAC什么时候.有时因各种错误加载错误ASM实例或LISTENER显示器,或增加CLUSTERWARE资源,但并没有真正的工作,例如: 如图所看到的,这里在2个节点分别创建过ASM1和AS ...