一、背景

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排查的更多相关文章

  1. 【源码】Redis exists命令bug分析

    本文基于社区版Redis 4.0.8 1.复现条件 版本:社区版Redis 4.0.10以下版本 使用场景:开启读写分离的主从架构或者集群架构(master只负责写流量,slave负责读流量) 案例: ...

  2. Redis常用命令

    Redis常用命令Redis提供了丰富的命令对数据库和各种数据类型进行操作,这些命令可以再Linux终端使用.1.键值相关命令2.服务器相关命令 一.键值相关命令 1.get get 键值 当 key ...

  3. 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 ...

  4. 转:redis常用命令

    一 Redis介绍 Redis是一个开源的使用ANSI C语言编写.支持网络.可基于内存亦可持久化的日志型.Key-Value数据库,并提供多种语言的API.从2010年3月15日起,Redis的开发 ...

  5. Redis监控工具,命令和调优

    Redis监控工具,命令和调优 1.图形化监控 因为要对Redis做性能测试,发现了GitHub上有个python写的RedisLive监控工具评价不错.结果鼓捣了半天,最后发现其主页中引用了Goog ...

  6. redis redis常用命令及内存分析总结(附RedisClient工具简介

    redis常用命令及内存分析总结(附RedisClient工具简介 by:授客 QQ:1033553122 redis-cli工具 查看帮助 连接redis数据库 常用命令 exists key se ...

  7. 【Redis】命令学习笔记——键(key)(20个超全字典版)

    安装完redis和redis-desktop-manager后,开始学习命令啦!本篇基于redis 4.0.11版本,从对键(key)开始挖坑! 准备工作,使用db1(默认db0,由于之前练习用db0 ...

  8. redis 的命令总结

    此博客为技术收集和个人的学习积累,如侵犯了您的权益,请联系我,我会及时删除,谢谢 [Redis] redis-cli 命令总结 Redis提供了丰富的命令(command)对数据库和各种数据类型进行操 ...

  9. redis --------- 使用命令(每天一个)

    Key(键) Del     语法:DEL  Key [key ...]     删除给定的一个或者多个key  不存在的key会被忽略. 返回值: 被删粗key的数量# 删除单个 key redis ...

随机推荐

  1. Sleep(0)的妙用

    在线程中,调用sleep(0)可以释放cpu时间,让线程马上重新回到就绪队列而非等待队列,sleep(0)释放当前线程所剩余的时间片(如果有剩余的话),这样可以让操作系统切换其他线程来执行,提升效率. ...

  2. JavaCPP 技术使用经验总结

    本文是对 JNI 技术的一个补充方法,提出了替换 JNI.JNA 的一种开源技术.首先对 JavaCPP 技术进行简单介绍及对应于其他现有方案的介绍.对比.接下来,通过一个简单的示例让大家了解 Jav ...

  3. Struts2——(6)表单校验

    一.表单校验 js,jquery是客户端校验,今天要说的是客户端校验. 禁止js,或者机器代码会破坏客户端校验,所以客户端校验相对不安全. 服务器端校验是基于java代码在服务器端进行校验,特点是相应 ...

  4. android 创建一个新的每次project什么时候 请问自己主动 参加 V7依赖?

    android 创建一个新的每次project什么时候 请问自己主动 参加 V7依赖? 分析原因: 主要是由于.我之前的 SDK 的版本号 更新的有点高了.低版本号是不会有这样的问题g的,新版本号中g ...

  5. Android TV开发中所有的遥控器按键监听及注意事项,新增home键监听

    原文:Android TV开发中所有的遥控器按键监听及注意事项,新增home键监听 简单记录下android 盒子开发遥控器的监听 ,希望能帮到新入门的朋友们 不多说,直接贴代码 public cla ...

  6. 利用WPF的ListView进行大数据量异步加载

    原文:利用WPF的ListView进行大数据量异步加载 由于之前利用Winform的ListView进行大数据量加载的时候,诟病良多,所以今天试着用WPF的ListView来做了一下,结果没有让我失望 ...

  7. 非参贝叶斯(Bayesian Non-parameter)初步

    0. motivations 如何确定 GMM 模型的 k,既观察到的样本由多少个高斯分布生成.由此在数据属于高维空间中时,根本就无法 visualize,更加难以建立直观,从而很难确定 k,高斯分布 ...

  8. Word 公式排版(使用制表符)

    公式的构成: 公式: 右编号: 法一:使用 3 行 1 列的表格 Word论文写作如何实现公式居中.编号右对齐_百度经验 修改三个单元格之间的长度比例关系时,其位置是在: [表格属性]⇒ [单元格]选 ...

  9. html5 模糊匹配搜索框

    使用bootstrap3-typeahead.js 文件在这里 引用: <script type="text/javascript" src="@Url.Conte ...

  10. Prism框架在项目中使用

    本文大纲 1.Prism框架下载和说明 2.Prism项目预览及简单介绍. 3.Prism框架如何在项目中使用. Prism框架下载和说明 Prism框架是针对WPF和Silverlight的MVVM ...