Redis EXISTS命令耗时过长case排查
一、背景
redis慢日志分析平台上线后,随便看了一下,发现onestore使用的缓存集群,存在大量的EXISTS命令慢查询的情况:

平均每个EXISTS命令需要13ms,最大耗时近20ms。这个结果很不科学啊,EXISTS命令只是执行一次hash查找操作,应该是us级别。
和相关同学了解业务背景如下:
- 业务是userfeed,存放用户发表的动态
- 使用zset存储一个用户发表的所有动态,key是用户id,集合中对应的是feedid。如果用户发表的动态很多,zset也很大
- redis集群作为onestore的缓存,过期时间是10分钟
- 在访问cache前会调用EXISTS查看是否命中,如果不命中就用onestore回填cache
由于一些用户发表的动态很多(2W+),所以存在很多的ZADD慢查询。
二、排查
1. redis的清除过期key的策略
- 被动方式:在事件循环中,每秒执行约10次,尽力删除过期的key,会有漏掉的情况
- 从expire set中随机检查20个key
- 删除到过期的key
- 如果超过25%的key都是过期了,就重复第一步(超过25%说明过期的key占比很多)
- 主动方式:
- 如果该key在被动方式中漏过,在其再次被访问时检查并清除
2. 查看代码
void existsCommand(redisClient *c) {
expireIfNeeded(c->db,c->argv[1]); // 检查该key是否过期,如果过期就delete掉
if (dbExists(c->db,c->argv[1])) {
addReply(c, shared.cone);
} else {
addReply(c, shared.czero);
}
}
在EXISTS命令处理函数中实现了清除过期key的主动策略,会先调用expireIfNeeded函数检查要访问的key是否过期,如果过期就delete掉这个key。del命令在删除元素很多的复合数据类型(list、hash、zset、set)时是一个很耗时的操作。由于存在元素很多的zset,和ZADD一样,在删除zset时需要一个一个遍历所有元素,时间复杂度是大O(n)。由于这个删除操作在EXISTS命令的处理函数中执行,所以导致EXISTS耗时过长。
3. redis慢日志验证
通过慢日志可以验证上述结论

- EXISTS先检查‘user:94479529:feed’是否存在,该key已经过期,触发主动过期机制,将该key删除
- 从onestore获取该key的数据,然后通过ZADD回填
三、风险
该集群单个实例qps达到8k+,同时每天有10W+的慢查询。在redis存在大量慢查询时,会存在个别客户端超时的情况,导致请求失败。
四、后续处理
1. 增加过期时间,由10分钟到20分钟
2. 对redis集群扩容(试增加过期时间的效果而定)
对于redis删除大key耗时的问题,redis作者提供了解决方案,具体就是使用异步线程对大key进行删除操作,避免阻塞主线程。
Redis EXISTS命令耗时过长case排查的更多相关文章
- 【源码】Redis exists命令bug分析
本文基于社区版Redis 4.0.8 1.复现条件 版本:社区版Redis 4.0.10以下版本 使用场景:开启读写分离的主从架构或者集群架构(master只负责写流量,slave负责读流量) 案例: ...
- Redis常用命令
Redis常用命令Redis提供了丰富的命令对数据库和各种数据类型进行操作,这些命令可以再Linux终端使用.1.键值相关命令2.服务器相关命令 一.键值相关命令 1.get get 键值 当 key ...
- Benchmark result without MONITOR running: Benchmark result with MONITOR running (redis-cli monitor > /dev/null): 吞吐量 下降约1半 Redis监控工具,命令和调优
https://redis.io/commands/monitor In this particular case, running a single MONITOR client can reduc ...
- 转:redis常用命令
一 Redis介绍 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.从2010年3月15日起,Redis的开发 ...
- Redis监控工具,命令和调优
Redis监控工具,命令和调优 1.图形化监控 因为要对Redis做性能测试,发现了GitHub上有个python写的RedisLive监控工具评价不错.结果鼓捣了半天,最后发现其主页中引用了Goog ...
- redis redis常用命令及内存分析总结(附RedisClient工具简介
redis常用命令及内存分析总结(附RedisClient工具简介 by:授客 QQ:1033553122 redis-cli工具 查看帮助 连接redis数据库 常用命令 exists key se ...
- 【Redis】命令学习笔记——键(key)(20个超全字典版)
安装完redis和redis-desktop-manager后,开始学习命令啦!本篇基于redis 4.0.11版本,从对键(key)开始挖坑! 准备工作,使用db1(默认db0,由于之前练习用db0 ...
- redis 的命令总结
此博客为技术收集和个人的学习积累,如侵犯了您的权益,请联系我,我会及时删除,谢谢 [Redis] redis-cli 命令总结 Redis提供了丰富的命令(command)对数据库和各种数据类型进行操 ...
- redis --------- 使用命令(每天一个)
Key(键) Del 语法:DEL Key [key ...] 删除给定的一个或者多个key 不存在的key会被忽略. 返回值: 被删粗key的数量# 删除单个 key redis ...
随机推荐
- Sleep(0)的妙用
在线程中,调用sleep(0)可以释放cpu时间,让线程马上重新回到就绪队列而非等待队列,sleep(0)释放当前线程所剩余的时间片(如果有剩余的话),这样可以让操作系统切换其他线程来执行,提升效率. ...
- JavaCPP 技术使用经验总结
本文是对 JNI 技术的一个补充方法,提出了替换 JNI.JNA 的一种开源技术.首先对 JavaCPP 技术进行简单介绍及对应于其他现有方案的介绍.对比.接下来,通过一个简单的示例让大家了解 Jav ...
- Struts2——(6)表单校验
一.表单校验 js,jquery是客户端校验,今天要说的是客户端校验. 禁止js,或者机器代码会破坏客户端校验,所以客户端校验相对不安全. 服务器端校验是基于java代码在服务器端进行校验,特点是相应 ...
- android 创建一个新的每次project什么时候 请问自己主动 参加 V7依赖?
android 创建一个新的每次project什么时候 请问自己主动 参加 V7依赖? 分析原因: 主要是由于.我之前的 SDK 的版本号 更新的有点高了.低版本号是不会有这样的问题g的,新版本号中g ...
- Android TV开发中所有的遥控器按键监听及注意事项,新增home键监听
原文:Android TV开发中所有的遥控器按键监听及注意事项,新增home键监听 简单记录下android 盒子开发遥控器的监听 ,希望能帮到新入门的朋友们 不多说,直接贴代码 public cla ...
- 利用WPF的ListView进行大数据量异步加载
原文:利用WPF的ListView进行大数据量异步加载 由于之前利用Winform的ListView进行大数据量加载的时候,诟病良多,所以今天试着用WPF的ListView来做了一下,结果没有让我失望 ...
- 非参贝叶斯(Bayesian Non-parameter)初步
0. motivations 如何确定 GMM 模型的 k,既观察到的样本由多少个高斯分布生成.由此在数据属于高维空间中时,根本就无法 visualize,更加难以建立直观,从而很难确定 k,高斯分布 ...
- Word 公式排版(使用制表符)
公式的构成: 公式: 右编号: 法一:使用 3 行 1 列的表格 Word论文写作如何实现公式居中.编号右对齐_百度经验 修改三个单元格之间的长度比例关系时,其位置是在: [表格属性]⇒ [单元格]选 ...
- html5 模糊匹配搜索框
使用bootstrap3-typeahead.js 文件在这里 引用: <script type="text/javascript" src="@Url.Conte ...
- Prism框架在项目中使用
本文大纲 1.Prism框架下载和说明 2.Prism项目预览及简单介绍. 3.Prism框架如何在项目中使用. Prism框架下载和说明 Prism框架是针对WPF和Silverlight的MVVM ...