redis模糊批量清除key
有时候需要从 Redis 实例成千上万的 key 中找出特定前缀的 key 列表来手动处理数据,可能是修改它的值,也可能是删除 key。这里就有一个问题,如何从海量的 key 中找出满足特定前缀的 key 列表来?
一、命令行删除
redis-cli -h 172.18.255.99 -p 6379 -n 6 -a 123456 KEYS "websocket127.0.0.1:5*" | xargs redis-cli -h 172.18.255.99 -p 6379 -n 6 -a 123456 DEL
- -h:redis地址
- -p:redis端口
- -n:reids库
- -a:redis密码
Redis 提供了一个简单暴力的指令 keys 用来列出所有满足特定正则字符串规则的 key。
注:这个指令使用非常简单,提供一个简单的正则字符串即可,但是有很明显的两个缺点。
- 没有 offset、limit 参数,一次性吐出所有满足条件的 key,万一实例中有几百 w 个 key 满足条件,
- 当你看到满屏的字符串刷的没有尽头时,你就知道难受了。
- keys 算法是遍历算法,复杂度是 O(n),如果实例中有千万级以上的 key,这个指令就会导致 Redis 服务卡顿,
- 所有读写 Redis 的其它的指令都会被延后甚至会超时报错,
- 因为 Redis 是单线程程序,顺序执行所有指令,其它指令必须等到当前的 keys 指令执行完了才可以继续。
所以建议生产环境屏蔽keys命令
scan 相比 keys 具备有以下特点:
-
复杂度虽然也是 O(n),但是它是通过游标分步进行的,不会阻塞线程;
-
提供 limit 参数,可以控制每次返回结果的最大条数,limit 只是对增量式迭代命令的一种提示(hint),返回的结果可多可少;
-
同 keys 一样,它也提供模式匹配功能;
-
服务器不需要为游标保存状态,游标的唯一状态就是 scan 返回给客户端的游标整数;
-
返回的结果可能会有重复,需要客户端去重复,这点非常重要;
-
遍历的过程中如果有数据修改,改动后的数据能不能遍历到是不确定的;
-
单次返回的结果是空的并不意味着遍历结束,而要看返回的游标值是否为零
-
KEYS vs SCAN
一樣都會掃過所有的 key,scan 不會阻塞整個 server,而是迭代的收集結果
- DEL vs UNLINK
一樣都是刪除 key ,差別在於 unlink 是非阻塞的刪除,會以非同步的方式回收記憶體
所以对于一个大的key数量,我们可以借助sscan使用下边的命令可以实现优雅的批量删除:
redis-cli -h 172.18.255.99 -p 6379 --scan --pattern users:* | xargs redis-cli -h 172.18.255.99 -p 6379 unlink
- 用 scan 找出要刪的 key
- 透過 xargs 傳給 unlink 刪掉 key
(error) ERR unknown command 'unlink'
如果出现以上错误,说明redis版本不足,使用unlink需要Redis4版本
cluster 删除数据
redis-cli -c -p 7000 --scan --pattern "age_*" | xargs -L 1 redis-cli -c -p 7000 -n 0 unlink
遍历redis cluster各分片删除
for port in {7000..7005}; do
redis-cli -c -p ${port} -h 192.168.31.181 --scan --pattern "age_*" | xargs -L 1 redis-cli -h 192.168.31.181 -c -p ${port} -n 0 unlink
done
二、golang代码删除
func DeleteRedisKeys(key string) {
traceId := libra.GenTraceId(context.Background(), nil)
ctx := libra.SetTraceId(context.Background(), traceId)
//模糊查询所有符合条件的key
websocketKeys, _ := commons.GetRedisClient().Keys(ctx, key "*").Result()
if reflect.TypeOf(websocketKeys).Kind() == reflect.Slice {
val := reflect.ValueOf(websocketKeys)
if val.Len() == 0 {
return
}
// 批量删除key
for i := 0; i < val.Len(); i {
_, err := commons.GetRedisClient().Del(ctx, val.Index(i).Interface().(string)).Result()
dlog.Errorf("DeleteKeys addr:=%v,err=%v", addr, err)
}
}
}
参考文档:
- Redis SCAN的使用:http://jinguoxing.github.io/redis/2018/09/04/redis-scan/
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanhgfibkj
系列文章
更多
同类精品
更多
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
怎样阻止微信小程序自动打开
PHP中文网 06-13 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01