一文弄懂Redis慢查询
什么是Redis慢查询?
redis的"慢查询"与redis定义慢查询的时间阈值有关,Redis提供了slowlog-log-slower-than和slowlog-max-len两个配置,slowlog-log-slower-than指当redis命令的执行时间超过该值时,redis会将其记录在redis的慢查询日志中,slowlog-max-len表示记录的条数(超过时会只存储最新的slowlog-max-len条),slowlog-log-slower-than的默认值为10000us,也就是一般来说,redis命令执行时间超过10ms时,我们认为产生了慢查询,redis慢查询日志记录的是执行时间,没有慢查询,并不表示客户端没有超时问题,有可能网络传输有延迟,也有可能排队的命令比较多,导致redis查询也很慢。
产生慢查询有哪些原因?
在业务使用过程中,我们发现redis使用上出现慢查询的原因有主要以下几种:
- 使用复杂度过高的命令
- 大key问题
- 集中过期
如何解决慢查询问题?
针对上述的原因,下面逐个给出导致慢查询的原因细节,并提出对应解决redis慢查询的有效方法。
使用复杂度过高的命令
负责的命令一般指O(N)以上的命令,比如sort、sunion、zunionstore聚合类的命令,或是O(N)类的命令,但是N的值由于业务原因特别大。
对于O(N)以上的命令,redis在操作内存数据时,耗时过高,会耗费更多的cpu资源,导致查询变慢。对于O(N)类的命令,由于N的值特别大Redis 一次需要返回给客户端的数据过多,更多时间花费在数据协议的组装和网络传输过程中。
除此之外,我们都知道,Redis 是单线程处理客户端请求的,如果你经常使用以上命令,那么当 Redis 处理客户端请求时,一旦前面某个命令发生耗时,就会导致后面的请求发生排队,对于客户端来说,响应延迟也会长。
针对此类原因,我们一般有以下两个原则:
- 尽量不使用O(N)以上复杂度的命令,某些数据排序或聚合操作,可以放在客户端处理。
- 执行O(N)命令时,保证 N 尽量的小(推荐 N <= 300 经验值),每次获取尽量少的数据,让 Redis 可以及时处理返回。
大key问题
所谓大key问题其实并不是值key过大,实则值key对应的value的值过大,此类问题在SET / DEL这类命令中也常出现慢查询。
首先我们要了解下redis写入与删除数据做了什么:
- 写入数据:为该数据分配内存。
- 删除数据:释放该数据对应的内存空间。
很明显,当数据值比较大时,redis分配数据内存或释放空间内存都会比较耗时,针对大key问题,有以下建议:
- 尽量避免写入大key(不要写入无关的数据,数据实在过大可以进行拆分,通过多key存储)
- 如果你使用的 Redis 是 4.0 以上版本,用 UNLINK 命令替代 DEL,此命令可以把释放 key 内存的操作,放到后台线程中去执行,从而降低对 Redis 的影响
- 如果你使用的 Redis 是 6.0 以上版本,可以开启 lazy-free 机制(lazyfree-lazy-user-del = yes),在执行 DEL 命令时,释放内存也会放到后台线程中执行。
顺边提下检测大key的一个命令:
redis-cli -h 127.0.0.1 -p 6379 --bigkeys -i 0.01
输出结果会展示每种数据类型所占用的最大内存 / 拥有最多元素的 key 是哪一个,以及每种数据类型在整个实例中的占比和平均大小 / 元素数量。
其实,使用这个命令的原理,就是 Redis 在内部执行了 SCAN 命令,遍历整个实例中所有的 key,然后针对 key 的类型,分别执行 STRLEN、LLEN、HLEN、SCARD、ZCARD 命令,来获取 String 类型的长度、容器类型(List、Hash、Set、ZSet)的元素个数。
这里我需要提醒你的是,当执行这个命令时,要注意 2 个问题:
- 对线上实例进行 bigkey 扫描时,Redis 的 OPS 会突增,为了降低扫描过程中对 Redis 的影响,最好控制一下扫描的频率,指定 -i 参数即可,它表示扫描过程中每次扫描后休息的时间间隔,单位是秒
- 扫描结果中,对于容器类型(List、Hash、Set、ZSet)的 key,只能扫描出元素最多的 key。但一个 key 的元素多,不一定表示占用内存也多,你还需要根据业务情况,进一步评估内存占用情况
集中过期
集中过期产生的慢查询很容易被忽略,可能我们在业务上线时,并没有发生慢查询,而是业务运行时在某个时间点总是突然发生慢查询。为什么集中过期会导致慢查询呢?我们首先了解下redis的两种过期策略:
- 被动过期:只有当访问某个key时,才会检测该key是否已经过期,如果已经过期则从实例删除该key。
- 主动过期:redis内部存在一个定时任务,默认每间隔100毫秒就会从全局的过期哈希表里面随机取出20个key,然后删除其中过期的 key,如果过期 key 的比例超过了 25%,则继续重复此过程,直到过期 key 的比例下降到 25% 以下,或者这次任务的执行耗时超过了 25 毫秒,才会退出循环。
值得注意的是,主动过期key的定时任务是在redis主线程种执行的,也就是说如果在执行主动过期的过程中,出现了集中过期,那就需要大量删除过期 key ,那么此时应用程序在访问 Redis 时,必须要等待这个过期任务执行结束,Redis 才可以服务这个客户端请求,此时应用访问 Redis 就可能产生查询。
如果此时需要过期删除的是一个 bigkey,那么这个耗时会更久。而且,这个操作延迟的命令并不会记录在慢日志中。
因为慢日志中只记录一个命令真正操作内存数据的耗时,而 Redis 主动删除过期 key 的逻辑,是在命令真正执行之前执行的。
对于集中过期问题,有以下建议
- 避免集中过期,比如将过期时间随机化,添加一个随机的值,分散集中过期的key的过期时间,降低 Redis 清理过期 key 的压力
- 对于Redis 是 4.0 以上版本,可以开启 lazy-free 机制,当删除过期 key 时,把释放内存的操作放到后台线程中执行,避免阻塞主线程
总结
本文介绍了redis慢查询的含义,列举了业务使用种常导致redis慢查询的几个原因以及对应的解决办法,希望大家有所收获。
一文弄懂Redis慢查询相关推荐
- 一文弄懂redis分布式缓存之微博推送技术方案
1️⃣业务场景分析 关注微博 登录首页展示了我关注的所有人发的微博,展示形式是列表 滚动有分页加载 2.个人微博 我发的微博展示在个人微博,展示形式也是列表 滚动有分页加载 2️⃣ 基于redis技术 ...
- 一文弄懂元学习 (Meta Learing)(附代码实战)《繁凡的深度学习笔记》第 15 章 元学习详解 (上)万字中文综述
<繁凡的深度学习笔记>第 15 章 元学习详解 (上)万字中文综述(DL笔记整理系列) 3043331995@qq.com https://fanfansann.blog.csdn.net ...
- 程序员,想要彻底弄懂Redis,这15点你一定要明白~(纯干货)
点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:Java实现QQ登录和微博登录个人原创+1博客:点击前往,查看更多 作者:耿直的小码农 来源:https://s ...
- 面试必问:一文弄懂MySQL数据库索引之底层数据结构和索引类型
面试必问:一文弄懂MySQL数据库索引之底层数据结构和索引类型 前言 一.索引 1.1作用 1.2特点 1.3使用 1.3.1创建索引 1.3.2删除索引 1.3.3查看表中的索引 1.3.4查看SQ ...
- 一文弄懂神经网络中的反向传播法
最近在看深度学习的东西,一开始看的吴恩达的UFLDL教程,有中文版就直接看了,后来发现有些地方总是不是很明确,又去看英文版,然后又找了些资料看,才发现,中文版的译者在翻译的时候会对省略的公式推导过程进 ...
- 一文弄懂各种loss function
有模型就要定义损失函数(又叫目标函数),没有损失函数,模型就失去了优化的方向.大家往往接触的损失函数比较少,比如回归就是MSE,MAE,分类就是log loss,交叉熵.在各个模型中,目标函数往往都是 ...
- 一文弄懂神经网络中的反向传播法——BackPropagation【转】
本文转载自:https://www.cnblogs.com/charlotte77/p/5629865.html 一文弄懂神经网络中的反向传播法--BackPropagation 最近在看深度学习的东 ...
- 一文弄懂String的所有小秘密
文章目录 简介 String是不可变的 传值还是传引用 substring() 导致的内存泄露 总结 一文弄懂String的所有小秘密 简介 String是java中非常常用的一个对象类型.可以说ja ...
- 一文弄懂EnumMap和EnumSet
文章目录 简介 EnumMap 什么时候使用EnumMap EnumSet 总结 一文弄懂EnumMap和EnumSet 简介 一般来说我们会选择使用HashMap来存储key-value格式的数据, ...
最新文章
- aria2下载工具命令行和图形化界面使用
- clojure入门: hello world
- SDN和SD-WAN有本质区别—Vecloud微云
- BZOJ 1085 [SCOI2005]骑士精神 【A*启发式搜索】
- 深入信号和槽(Signals and Slots in Depth)
- Valid Number
- 人工智能在建筑运营_打造智能建筑商
- 获取json配置_ASP.NET Core集成Nacos配置中心之适配多格式配置
- SQL中的左连接和右连接
- 计算机与宽带路由的连接步骤,宽带拨号和设置路由器步骤【图】
- SAS硬盘安装Windows 7操作方法
- 广度优先遍历搜索的最通俗介绍,如何实现广度优先搜索算法?广度优先遍历搜索可用于哪些行业?
- MATLAB实现语音信号的读取
- pixhawk编译环境搭建--2018.4.25
- 虚幻5新特性之EnhancedInput
- oracle数据库建立外键级联删除
- 【Linux】Linux进程控制(学习复习兼顾)
- JavaScript中this的指向
- 第1讲韩顺平 PHP视频教程 zend framework zend介绍 zend快速入门 韩顺平php视频教程ppt 笔记心得
- Linux、window服务器下创建共享文件夹(方便于局域网内进行文件共享)
热门文章
- 最大似然估计(机器学习)
- 【Pyecharts50例】GEO图中忽略不存在的位置
- css中float问题,列表中的css float问题
- 宇宙最强IDE!微软正式宣布 Visual Studio 2019
- linux中write的实例,Linux内核 down_write()
- Ubuntu14.04 LTS更新源
- GCN学习:Pytorch-Geometric教程(二)
- Home Assistant初学者指南 - 5 之 如何在Home Assistant中设置Picture Elements卡 - Lovelace
- swiper.js显示指定图片
- Mysql数据库使用规范