Redis scan等命令的学习与研究

redis,scan,命令,学习,研究 · 浏览次数 : 58

小编点评

**Redis scan 命令学习与研究摘要** **引言** Redis scan 命令是解决 keys 命令一次全部键值对扫描导致的 O(n) 时间复杂度的方法。 **scan 命令** scan 命令仅会在 count 范围内的键值对进行匹配,并将匹配结果返回。 **优化** scan 命令使用游标来提高性能,但它存在一个问题:在 monitor 命令中使用 scan 0 时,需要返回配置的键值对,并返回下一个测试使用的游标。 **其他命令** 除了 scan 命令外,还有其他命令可以用于键值对扫描,例如 del 命令用于删除键值对,而 unlink 命令用于异步删除键值对。 **性能测试** Redis 4.0 时增加了 unlink 方法,以提高键值对查找性能。 **间隙执行** 间隙是 scan 命令执行之间的短暂暂停,可以用于将业务命令添加到 Redis 进行执行。 **时间复杂度** scan 命令的时间复杂度取决于键值对数量和 count。

正文

Redis scan等命令的学习与研究


摘要

背景跟前几天说的一个问题类似.
为了验证自己的设想, 所以晚上继续写脚本进行了一轮次的验证. 

不过上次讨论时,打击好像都没听懂我说的
所以这次准备从基础开始讲起. 
很多好东西在上来量之后可能会变成坏东西

scan 命令

Redis 在2.8 之后增加了scan命令.
其实scan命令是为了解决keys 命令一次全部键值对扫描导致的O(n)时间复杂度而来.

keys zhaobsh* 会递归查寻所有的键值对, 返回前缀是 zhaobsh的键值对信息. 

scan 0 match zhaobsh* count 10000  
scan命令仅会在count范围内的键值对进行匹配, 匹配完成后返回键值对信息. 

表面上看起来scan是避免了keys 键值对全部扫描的性能损耗, 在大量key的情况下避免太大的延迟.
但是scan 是存在一个游标的. 
第一次count范围内 匹配完不仅要返回配置的键值对, 还要返回下一个测试使用的游标. 

所以在monitor的命令里面.  SCAN 0 为特征, 是一组scan命令. 
其他的都会根据scan 0 返回的游标进行递归查询, 理论上 count 10000 时, 有多少万个键值对.
就有有多少个 scan命令数(键值对数量向上取整)

我这边也进行了一定程度的学习与研究
scan 之间会插入一些命令. 

通过monitor 监控 scan 非0游标之间的命令数就可以发现. 

但是scan命令也是存在一个比keys 命令要差的地方
keys 会直接返回最终的结果, 命令交互也少
scan 命令会多次执行交互, 最终返回结果

scan 仅是避免了被长久的阻塞, 但是实际上他会使用更多的CPU时间和周期来进行键值对查找. 

del 命令其实比较简单, 就是直接进行了一次 删除
时间复杂度也是 O(1) 

但是删除命令 是需要释放内存的.
如果是一个大的key 内存清理也比较费时. 

为了提高性能 redis 4.0 时增加了unlink的方法

1:del和unlink的最大区别是del是同步删除,unlink是异步删除
2:对于线上使用删除的尽量不要使用del,因为同步删除可能会造成本身服务停顿,特别是业务量特别依赖redis的服务。
3:redis的value删除之后的内存回收使用的引用计算器算法。

其实不建议进行 del  del 同步删除, 尤其是 大key时会有较久的时间等待. 
现在del的命令其实很多, 改成unlink 其实也有风险

这里简单做一下实验
先插入1000万key
然后在执行 1000万个unlink的处理. 

查看内存情况.
插入完的情况为:
used_memory:857426752
used_memory_human:817.71M
allocator_frag_ratio:1.00
allocator_frag_bytes:3140072
注意 此时我的内存策略为:
maxmemory:0
maxmemory_human:0B
maxmemory_policy:noeviction

执行完 unlink的情况为:
used_memory:3216848
used_memory_human:3.07M
mem_fragmentation_ratio:19.43
mem_fragmentation_bytes:58503480

会发现会慢慢的  碎片率会慢慢的下降. 

一万个 set    耗时 19秒
一万个 unlink 耗时 18秒
一万个 del    耗时 10秒

关于scan的研究

scan 会有一个间隙执行命令的操作
通过这个间隙, 可以将业务命令添加到redis进行执行.
这种情况下间隙之间执行的命令, 可以进行业务操作与处理.
但是如果scan太多, 可能导致执行命令的管道被scan命令阻塞.
出现耗时严重的问题

关于redis的时间复杂度

1. Redis在进行benchmark压测时能够发现, 可以支撑10万级别的IOPS
   换算出来 10微秒执行一个命令
2. 但是我理解这个10微秒, 在redis核心进程中的时间其实很短,估计只有1微秒左右. 
   其他的时间其实是网络栈交互等等操作. 
3. 如果scan的命令数较大,就会发现他的 slowlog 大概是每一万个key 10毫秒
   如果是10000万个key 执行 keys * 的耗时为 3.35秒 scan是11秒.

时间复杂度的算法其实是很复杂的 中间有很多损耗, 没法单独进行运算和处理. 

与Redis scan等命令的学习与研究相似的内容:

Redis scan等命令的学习与研究

Redis scan等命令的学习与研究 摘要 背景跟前几天说的一个问题类似. 为了验证自己的设想, 所以晚上继续写脚本进行了一轮次的验证. 不过上次讨论时,打击好像都没听懂我说的 所以这次准备从基础开始讲起. 很多好东西在上来量之后可能会变成坏东西 scan 命令 Redis 在2.8 之后增加了s

[转帖]Redis SCAN命令详解

https://www.jb51.net/article/257083.htm 处理一下.. SCAN 命令是一个基于游标的迭代器,每次被调用之后, 都会向用户返回一个新的游标, 用户在下次迭代时需要使用这个新游标作为 SCAN 命令的游标参数, 以此来延续之前的迭代过程,这篇文章给大家介绍了Red

[转帖]Redis Scan 原理解析与踩坑

https://www.lixueduan.com/posts/redis/redis-scan/ 主要分析了 Redis Scan 命令基本使用和具体实现,包括 Count 参数与 Scan 总耗时的关系,以及核心的逆二进制迭代算法分析。 1. 概述 由于 Redis 是单线程在处理用户的命令,而

[转帖]Redis Scan 原理解析与踩坑

https://www.cnblogs.com/jelly12345/p/16424080.html 1. 概述由于 Redis 是单线程在处理用户的命令,而 Keys 命令会一次性遍历所有 Key,于是在 命令执行过程中,无法执行其他命令。这就导致如果 Redis 中的 key 比较多,那么 Ke

[转帖]一次 Scan 竟耗时上百秒?Redis Scan 原理解析与踩坑

来自:指月 https://www.lixueduan.com原文:https://www.lixueduan.com/post/redis/redis-scan/主要分析了 Redis Scan 命令基本使用和具体实现,包括Count 参数与 Scan 总耗时的关系,以及核心的逆二进制迭代算法分析

[转帖]深入理解Redis的scan命令

熟悉Redis的人都知道,它是单线程的。因此在使用一些时间复杂度为O(N)的命令时要非常谨慎。可能一不小心就会阻塞进程,导致Redis出现卡顿。 有时,我们需要针对符合条件的一部分命令进行操作,比如删除以test_开头的key。那么怎么获取到这些key呢?在Redis2.8版本之前,我们可以使用ke

[转帖]redis中keys与scan命令的区别有哪些

https://www.yisu.com/zixun/445908.html 这篇文章将为大家详细讲解有关redis中keys与scan命令的区别有哪些,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。 redis keys和scan的区别 redis的keys命令,

[转帖]Redis中遍历大数据量的key:keys与scan命令

https://www.cnblogs.com/-wenli/p/13045432.html keys命令 keys * 、keys id:* 分别是查询全部的key以及查询前缀为id:的key。 缺点: 1、没有 offset、limit 参数,一次返回所有满足条件的 key。 2.keys算法是

Redis性能问题诊断以及scan命令耗时分析

Redis性能问题诊断以及scan命令耗时分析 摘要 最近公司有项目反馈卡顿. 卡顿一小时后自己被拉入群聊. 同事已经基本上定位到问题原因. 我这边想使用朴素的性能观点进行一下性能问题的拆解 为了提高自己. 用到的一些脚本 echo "info" |redis-cli -p 6379 -a Your

Redis如何批量删除指定前缀的key

批量删除指定前缀的Key有两中方法,一种是借助 `redis-cli`,另一种是通过 `SCAN` 命令来遍历所有匹配前缀的 key,并使用 `DEL` 命令逐个删除它们。 ## redis-cli 使用 Redis 自带的 `redis-cli` 命令行工具,你可以通过以下方式批量删除指定前缀的