Redis怎么删除数量过万以上Key而不影响业务
这篇文章主要介绍“Redis怎么删除数量过万以上Key而不影响业务”,在日常操作中,相信很多人在Redis怎么删除数量过万以上Key而不影响业务问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Redis怎么删除数量过万以上Key而不影响业务”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
需求
有时候因为 Redis Key 没有设置过期时间或者因为业务需求或者Redis内存不足或者修改Redis Key值等需求,并且这些Key是有规律的,可以通过正则表达式来匹配。
解决方法一
一般通过网上搜索,会告诉你使用下面方法,Redis 提供了一个简单暴力的指令 keys用来列出所有满足特定正则字符串规则的 key。
$ redis-cli --raw keys "testkey-*" | xargs redis-cli del
通过 Redis keys 来匹配你需要删除的key,再使用 xargs 把结果传给 redis-cli del ,这样看似完美,实则有很大风险。
上面命令使用非常简单,提供一个简单的正则字符串即可,但是有很明显的两个缺点。
没有 offset、limit 参数,一次性吐出所有满足条件的 key,万一实例中有几百 w 个 key 满足条件,当你看到满屏的字符串刷的没有尽头时,你就知道难受了。
keys 算法是遍历算法,复杂度是 O(n),如果实例中有千万级以上的 key,这个指令就会导致 Redis 服务卡顿,所有读写 Redis 的其它的指令都会被延后甚至会超时报错,因为 Redis 6 版本以下都是单线程程序,顺序执行所有指令,其它指令必须等到当前的 keys 指令执行完了才可以继续,这样就会导致业务不可用,甚至造成redis宕机的风险。
注意:这种方法不推荐,建议生产环境屏蔽keys命令。那大家会问,有没有更好的方法来解决这个问题?答案是当然用,请接着看下文。
解决方法二
Redis从2.8版本开始支持 scan 命令,SCAN命令的基本用法如下:
SCAN cursor [MATCH pattern] [COUNT count]
cursor:游标,SCAN命令是一个基于游标的迭代器,SCAN命令每次被调用之后,都会向用户返回一个新的游标,用户在下次迭代时需要使用这个新游标作为SCAN命令的游标参数,以此来延续之前的迭代过程,直到服务器向用户返回值为0的游标时,一次完整的遍历过程就结束了。
MATCH:匹配规则,例如遍历以 testkey- 开头的所有key可以写成 testkey-*。
COUNT:COUNT选项的作用就是让用户告知迭代命令,在每次迭代中应该从数据集里返回多少元素,COUNT只是对增量式迭代命令的一种提示,并不代表真正返回的数量,例如你COUNT设置为2有可能会返回3个元素,但返回的元素数据会与COUNT设置的正相关,COUNT的默认值是10。
例子:
$ scan 0 MATCH testkey-* 1) "34" 2) 1) "testkey-2" 2) "testkey-49" 3) "testkey-20" 4) "testkey-19" 5) "testkey-93" 6) "testkey-8" 7) "testkey-34" 8) "testkey-76" 9) "testkey-13" 10) "testkey-18" 11) "testkey-10" $ scan 34 MATCH testkey-* COUNT 1000 1) "0" 2) 1) "ops-coffee-16" 2) "ops-coffee-19" 3) "ops-coffee-23" 4) "ops-coffee-21" 5) "ops-coffee-40" 6) "ops-coffee-22" 7) "ops-coffee-1" 8) "ops-coffee-11" 9) "ops-coffee-28" 10) "ops-coffee-3" 11) "ops-coffee-26" 12) "ops-coffee-4" 13) "ops-coffee-31" ...
scan 命令返回的是一个包含两个元素的数组,第一个数组元素是用于进行下一次迭代的新游标,而第二个数组元素则是一个数组,这个数组中包含了所有被迭代的元素。
上面这个例子的意思是扫描所有前缀为testkey-的key。第一次迭代使用0作为游标,表示开始一次新的迭代,同时使用了MATCH匹配前缀为testkey-的key,返回了游标值34以及遍历到的数据。第二次迭代使用的是第一次迭代时返回的游标,也即是命令回复第一个元素的值34,同时通过将COUNT选项的参数设置为1000,强制命令为本次迭代扫描更多元素。在第二次调用SCAN命令时,命令返回了游标0,这表示迭代已经结束,整个数据集已经被完整遍历过了。
Redis scan 命令就是基于游标的迭代器,意味着命令每次被调用都需要使用上一次这个调用返回的游标作为该次调用的游标参数,以此来延续之前的迭代过程。当SCAN命令的游标参数被设置为0时,服务器将开始一次新的迭代,而当redis服务器向用户返回值为0的游标时,表示迭代已结束,这是唯一迭代结束的判定方式,而不能通过返回结果集是否为空判断迭代结束。
上面的需求,最终可以使用下面命令来解决:
$ redis-cli --scan --pattern "testkey-*" | xargs -L 1000 redis-cli del
xargs -L 指令表示xargs一次读取的行数,也就是每次删除key的数量,不要一次行读取太多数量key。
scan 与 keys 比较
scan 相比 keys 具备有以下特点:
复杂度虽然也是 O(n),但是它是通过游标分步进行的,不会阻塞线程。
提供 limit 参数,可以控制每次返回结果的最大条数,limit 只是对增量式迭代命令的一种提示(hint),返回的结果可多可少。
同 keys 一样,它也提供模式匹配功能。
服务器不需要为游标保存状态,游标的唯一状态就是 scan 返回给客户端的游标整数。
返回的结果可能会有重复,需要客户端去重复,这点非常重要。
遍历的过程中如果有数据修改,改动后的数据能不能遍历到是不确定的。
单次返回的结果是空的并不意味着遍历结束,而要看返回的游标值是否为零。
小结
Redis 类似 scan 命令还有很多,比如:
scan 指令是一系列指令,除了可以遍历所有的 key 之外,还可以对指定的容器集合进行遍历
zscan 遍历 zset 集合元素
hscan 遍历 hash 字典的元素
sscan 遍历 set 集合的元素
注意:SSCAN 命令、 HSCAN 命令和 ZSCAN 命令的第一个参数总是一个数据库键。而 SCAN 命令则不需要在第一个参数提供任何数据库键,因为它迭代的是当前数据库中的所有数据库键。
到此,关于“Redis怎么删除数量过万以上Key而不影响业务”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341