当前位置: 首页 > 科技观察

Redis如何删除数量过万以上Key而不影响业务

时间:2023-03-12 04:51:22 科技观察

Redis如何在不影响业务需求的情况下删除10000多个Key?有时因为RedisKey没有设置过期时间,或者因为业务需求,Redis内存不足,或者修改RedisKey值等需求,而这些Key是正则的,可以通过正则表达式来匹配。解决方案1??一般在网上搜索,都会告诉你使用下面的方法。Redis提供了一种简单粗暴的指令keys来列出所有符合特定正则字符串规则的keys。$redis-cli--rawkeys"testkey-*"|xargsredis-clidel使用Rediskey匹配你需要删除的key,然后使用xargs将结果传递给redis-clidel。这看起来很完美,但实际上风险很大。上面的命令使用起来非常简单,只是提供了一个简单的正则字符串,但是有两个明显的不足。没有offset和limit参数,一次性吐出所有满足条件的key。万一实例中有几百个w键符合条件,看到屏幕上的字符串没完没了就知道难受了。keys算法是一种复杂度为O(n)的遍历算法。如果实例中有千万级的key,这条指令会导致Redis服务卡死,其他所有读写Redis的指令都会延迟甚至超时。报错,因为Redis6及以下版本是单线程程序,顺序执行所有指令,其他指令必须等到当前keys指令执行完才能继续执行,会导致服务不可用,甚至有redis宕机的风险.注意:不推荐使用该方法,建议在生产环境中屏蔽keys命令。那么大家就会问,有没有更好的方法来解决这个问题呢?答案是肯定的,请往下看。方案二:Redis从2.8版本开始支持scan命令。SCAN命令的基本用法如下:SCANcursor[MATCHpattern][COUNTcount]cursor:游标,SCAN命令是一个基于游标的迭代器,每次调用SCAN命令都会发送给用户返回一个新的游标,用户需要在下一次迭代中使用这个新的游标作为SCAN命令的游标参数,从而继续之前的迭代过程,直到服务器返回一个值为0的游标给用户,一次完整的遍历过程就结束了。MATCH:匹配规则,例如遍历所有以testkey-开头的key,可以写成testkey-*。COUNT:COUNT选项的作用是让用户告诉迭代命令每次迭代应该从数据集中返回多少元素。COUNT只是对增量迭代命令的提示,并不代表实际返回的数量。比如你把COUNT设置为2,可能会返回3个元素,但是返回的元素数据会和COUNT设置正相关。COUNT的默认值为10。示例:$scan0MATCHtestkey-*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"$scan34MATCHtestkey-*COUNT10001)"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,表示迭代结束,遍历整个数据集。Redisscan命令是一个基于游标的迭代器,这意味着每次调用该命令时,都需要使用上一次调用返回的游标作为调用的游标参数,从而继续之前的迭代过程。当SCAN命令的cursor参数设置为0时,服务器会开始新的迭代,当redis服务器向用户返回值为0的cursor时,表示迭代结束。这是判断迭代结束的唯一方式,不能通过返回结果集是否为空来结束迭代。以上需求最终可以通过以下命令解决:$redis-cli--scan--pattern"testkey-*"|xargs-L1000redis-clidelxargs-L该指令表示xargs一次读取的行数,也就是每次删除的key个数,不要一次读取太多key。scan相对于keys有以下特点:虽然复杂度也是O(n),但是它是通过cursor一步步执行的,不会阻塞线程。提供limit参数来控制每次返回的最大结果数。limit只是对增量迭代命令的提示(hint),返回的结果可多可少。与键一样,它也提供模式匹配功能。服务器不需要为游标保存状态,游标的唯一状态是扫描返回给客户端的游标整数。返回的结果可能会重复,这就需要客户端重复,这一点很重要。如果遍历过程中有数据修改,修改后的数据能否遍历是不确定的。单个返回结果为空并不意味着遍历结束,而是取决于返回的游标值是否为零。总结Redis有很多类似的scan命令,例如:scan命令是一系列的命令。除了遍历所有的key,还可以遍历指定的容器集合。zscan遍历zset集合的元素hscan遍历hash字典的元素sscan遍历setElementsofSets注意:SSCAN命令,HSCAN命令,ZSCAN命令的第一个参数始终是数据库键。SCAN命令不需要在第一个参数中提供任何数据库键,因为它会迭代当前数据库中的所有数据库键。参考链接http://jinguoxing.github.io/redis/2018/09/04/redis-scan/https://juejin.cn/post/6844903869412016142