一、命令行删除
redis-cli-h172.18.255.99-p6379-n6-a123456KEYS"websocket127.0.0.1:5*"|xargsredis-cli-h172.18.255.99-p6379-n6-a123456DEL
-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返回给客户端的游标整数;
返回的结果可能会有重复,需要客户端去重复,这点非常重要;
遍历的过程中如果有数据修改,改动后的数据能不能遍历到是不确定的;
单次返回的结果是空的并不意味着遍历结束,而要看返回的游标值是否为零
KEYSvsSCAN
一樣都會掃過所有的key,scan不會阻塞整個server,而是迭代的收集結果
DELvsUNLINK
一樣都是刪除key,差別在於unlink是非阻塞的刪除,會以非同步的方式回收記憶體
所以对于一个大的key数量,我们可以借助sscan使用下边的命令可以实现优雅的批量删除:
redis-cli-h172.18.255.99-p6379--scan--patternusers:*|xargsredis-cli-h172.18.255.99-p6379unlink
用scan找出要刪的key
透過xargs傳給unlink刪掉key
(error)ERRunknowncommand'unlink'
如果出现以上错误,说明redis版本不足,使用unlink需要Redis4版本
cluster删除数据
redis-cli-c-p7000--scan--pattern"age_*"|xargs-L1redis-cli-c-p7000-n0unlink
遍历rediscluster各分片删除
forportin{7000..7005};do
redis-cli-c-p${port}-h192.168.31.181--scan--pattern"age_*"|xargs-L1redis-cli-h192.168.31.181-c-p${port}-n0unlink
done
二、golang代码删除
funcDeleteRedisKeys(keystring){
traceId:=libra.GenTraceId(context.Background(),nil)
ctx:=libra.SetTraceId(context.Background(),traceId)
//模糊查询所有符合条件的key
websocketKeys,_:=commons.GetRedisClient().Keys(ctx,key+"*").Result()
ifreflect.TypeOf(websocketKeys).Kind()==reflect.Slice{
val:=reflect.ValueOf(websocketKeys)
ifval.Len()==0{
return
}
//批量删除key
fori:=0;i<val.Len();i++{
_,err:=commons.GetRedisClient().Del(ctx,val.Index(i).Interface().(string)).Result()
dlog.Errorf("DeleteKeysaddr:=%v,err=%v",addr,err)
}
}
}
|