我想模糊删除 redis key🤔
前提
redis 中存在很多 key,可能随着业务的下架永远也用不到了,需要批量删除(当然也可以不处理,等 redis 内存不足的时候,自动去执行淘汰策略)。假设存在若干个如下模式的 key,都是以 unkey 为前缀,现在希望批量删除。
redis 2.6.0 之前
通过 del
直接删除(不推荐)
redis 官方中的 del
是不支持正则表达式的,但是你可以从网上找到相关的办法让 del
命令支持正则,因为不推荐,所有不展示
通过 shell
实现
redis 中的 KEYS 是支持通过正则表达式获取匹配的 key,然后通过管道传递给 xargs 进行删除
redis 2.6.0 之后
通过 Lua 脚本删除
redis 2.6.0 之后的版本支持通过 EVAL 或 EVALSHA 执行使用 Lua。 可以保证操作的原子性,还可以通过 script load
对脚本进行缓存,减少网络开销。使用 lua 有更高的自由度,可以添加很多功能模块。
基本流程是这样的,如果逻辑严谨的话,可以动态传入匹配的表达式,返回删除的 key 之类的逻辑。
redis 2.8.0 之后
通过 SCAN 替代 KEYS
redis 的执行是单线程的(至少当前版本是),如果我们通过 KEYS
去批量的获取 key,如果数量很大的话,会有问题:
没有 limit,只能一次获取所有,如果数据量很大的话全部输出的话,交互不友好。
keys 是遍历算法,时间复杂度是 O(n),如果数据量特别大的话,可能会导致服务卡顿,影响到正常业务。
如果我们用 SACN
替代的话,就会好很多:
时间复杂度虽然也是 O(n),但是它是通过游标分步进行的,不会阻塞线程
提供 limit 参数,控制返回的条数
但是这样写是有问题的,这还是一次获取所有 key,虽然每次都获取 1000 条,但是 lua 代码原子执行,还是会有一次获取很多阻塞线程的问题。
所有建议控制 每次获取的数量,然后多次执行,每次返回的游标给下次执行使用。
redis 4.0.0 之后
通过 UNLINK 替代 DEL
正常的 del
是在主线程内执行,等待当前的 del
执行完成,下一个命令才会执行。而 redis 在 4.0 之后提供了更好的选择。
unlink
会在另一个线程中执行内存的回收,不会阻塞正常的 get set 请求,而且使用的方式也很简单,跟执行 del
一样。
所以说 redis 4.0 之后就不再是单线程了,但是基本的操作还是在主线程内执行。
版权声明: 本文为 InfoQ 作者【山中兰花草】的原创文章。
原文链接:【http://xie.infoq.cn/article/0e34856ec9a88d749e7b1ae7a】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论