如何批量删除Redis下特定pattern的keys?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何批量删除Redis下特定pattern的keys?相关的知识,希望对你有一定的参考价值。

方案一:用keys ‘str*’ 列出要删除的key,接linux管道删除(linux命令行执行)
根据通配符查看待删除的 key : redis-cli KEYS "site_msg_999*”
借助 Linux 的 xargs 指令来完成这个动作:
如:
  */redis-cli keys "prefix*"
  如果是访问特定的数据库,则可以:
  */redis-cli -n 0 keys "prefix*"
  Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。
  redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
方案二:分两步先查询指定pattern的keys,再通过del key1 key2 key3 ...语句批量删除。

在redis的客户端环境中并不支持批量删除。
参考技术A   批量删除Redis下特定pattern的keys:
  可以使用linux的xargs来做到,如:
  */redis-cli keys "prefix*"
  如果是访问特定的数据库,则可以:
  */redis-cli -n 0 keys "prefix*"
  Redis是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可持久化的日志型、Key-Value数据库,并提供多种语言的API。从2010年3月15日起,Redis的开发工作由VMware主持。从2013年5月开始,Redis的开发由Pivotal赞助。
  redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset(sorted set --有序集合)和hash(哈希类型)。这些数据类型都支持push/pop、add/remove及取交集并集和差集及更丰富的操作,而且这些操作都是原子性的。在此基础上,redis支持各种不同方式的排序。与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。
参考技术B

方案一:用keys ‘str*’ 列出要删除的key,接linux管道删除(linux命令行执行)

    根据通配符查看待删除的 key :    redis-cli KEYS "site_msg_999*”

    借助 Linux 的 xargs 指令来完成这个动作:

    redis-cli keys "*" | xargs redis-cli del  //如果redis-cli没有设置成系统变量,需要指定redis-cli的完整路径,如:/etc/redis-cli keys "*" | xargs /etc/redis-cli del

方案二:分两步先查询指定pattern的keys,再通过del key1 key2 key3 ...语句批量删除。

参考技术C 在linux中 批量操作redis中的 keys的方法:
1.统计个数:

redis中名称含有OMP_OFFLINE的key的个数;

src/redis-cli keys "*OMP_OFFLINE*"|wc -l

2.批量删除
批量删除 0号数据库中名称含有OMP_OFFLINE的key:
src/redis-cli -n 0 keys "*OMP_OFFLINE*"|xargs src/redis-cli -n 0 del

在redis的客户端环境中并不支持批量删除。
参考技术D ShawKun,红灯硬闯,马路横穿
可以使用linux的xargs来做到 如:
*/redis-cli keys "prefix*" | xargs */redis-cli del
如果是访问特定的数据库,则可以:

*/redis-cli -n 0 keys "prefix*" | xargs */redis-cli -n 0 del

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/

以上是关于如何批量删除Redis下特定pattern的keys?的主要内容,如果未能解决你的问题,请参考以下文章

redis模糊批量清除key

redis怎么清除key值前几个字符相同的缓存

如何批量删除redis中keys

如何批量删除Redis数据库中的Key

k8s的docker环境下 , redis批量删除key

k8s的docker环境下 , redis批量删除key