资讯专栏INFORMATION COLUMN

如何批量删除Redis的key

inapt / 1343人阅读

摘要:使用此选项后,空格无论是否在引号中不会作为数据块的分隔符,只有换行会被作为数据块的分隔符。如果标准输入中没有任何非空的字符,则不运行命令默认情况下即使标准输入没有非空字符,命令也会被运行一

前戏

在laravel项目中发现了一个隐藏较深的问题,关于操作redis的increment方法:

$key = "exchange_".$num;
Cache::increment($key, 1);

该方法作用是将$key的值 +1 ,因为在增加之前没有作任何判断,当key不存在时, 内部会初始化这个key出来, 而因为这个key是没有传入过期时间的,导致这些key的过期时间是永久有效,即TTL= -1;

解决办法是在increment之前先判断是否存在这个key,存在则增加值,不存在则新建key即可


正文

问题来了: 由上面产生出来的一堆永久有效的key,如何删除呢?
有人想到: 用keys "exchange_*"搜索出来可以吗?

不可以!KEYS操作在线上是禁止使用的

我们知道,Redis是单线程的,如果量很大的话,keys是遍历key的,会导致阻塞,这样其他的客户端就没法连接了!那如何查找?

使用redis的scan命令 + linux的xargs

SCAN 命令

官网对于KEYS命令有一个提示: KEYS 的速度非常快,例如,Redis在一个有1百万个key的数据库里面执行一次查询需要的时间是40毫秒 。但在一个大的数据库中使用它仍然可能造成性能问题,如果你需要从一个数据集中查找特定的 KEYS, 你最好还是用 Redis 的集合结构 SETS 来代替。

但由于KEYS命令一次性返回所有匹配的key,所以,当redis中的key非常多时,对于内存的消耗和redis服务器都是一个隐患,
对于Redis 2.8以上版本给我们提供了一个更好的遍历key的命令 SCAN 该命令的基本格式:

SCAN cursor [MATCH pattern] [COUNT count]

SCAN 每次执行都只会返回少量元素,所以可以用于生产环境,而不会出现像 KEYS 或者 SMEMBERS 命令带来的可能会阻塞服务器的问题。
SCAN命令是一个基于游标的迭代器。这意味着命令每次被调用都需要使用上一次这个调用返回的游标作为该次调用的游标参数,以此来延续之前的迭代过程

当SCAN命令的游标参数(即cursor)被设置为 0 时, 服务器将开始一次新的迭代, 而当服务器向用户返回值为 0 的游标时, 表示迭代已结束。

COUNT选项

对于增量式迭代命令不保证每次迭代所返回的元素数量,我们可以使用COUNT选项, 对命令的行为进行一定程度上的调整。COUNT 选项的作用就是让用户告知迭代命令, 在每次迭代中应该从数据集里返回多少元素。使用COUNT 选项对于对增量式迭代命令相当于一种提示, 大多数情况下这种提示都比较有效的控制了返回值的数量。

注意:COUNT选项并不能严格控制返回的key数量,只能说是一个大致的约束。并非每次迭代都要使用相同的 COUNT 值,用户可以在每次迭代中按自己的需要随意改变 COUNT 值, 只要记得将上次迭代返回的游标用到下次迭代里面就可以了。

MATCH 选项

类似于KEYS 命令,增量式迭代命令通过给定 MATCH 参数的方式实现了通过提供一个 glob 风格的模式参数, 让命令只返回和给定模式相匹配的元素。

MATCH 选项对元素的模式匹配工作是在命令从数据集中取出元素后和向客户端返回元素前的这段时间内进行的, 所以如果被迭代的数据集中只有少量元素和模式相匹配, 那么迭代命令或许会在多次执行中都不返回任何元素。


Xargs命令

xargs指令可以从标准输入读取数据,并利用这些数据“组建”并“执行”指令。它的作用是将参数列表转换成小块分段传递给其他命令,以避免参数列表过长的问题。

语法
 xargs  [-0prtx]  [-E  eof-str]  [-e[eof-str]]  [--eof[=eof-str]]  [--null] 
  [-d  delimiter]  [--delimiter  delimiter]  [-I  replace-str]  
  [-i[replace-str]] [--replace[=replace-str]] [-l[max-lines]] 
  [-L max-lines] [--max-lines[=max-lines]] [-n max-args] 
  [--max-args=max-args]  [-s  max-chars] 
  [--max-chars=maxchars]  [-P  max-procs]  [--max-procs=max-procs] 
  [--process-slot-var=name]  [--interactive]  [--verbose]  [--exit]  
  [--no-run-if-empty]  [--arg-file=file] [--show-limits] [--version] 
  [--help] [command [initial-arguments]]
详解

xargs 从标准输入中读取使用“空格”或“空行”分隔的“数据块”,并以读入的“数据块”作为参数执行命令(默认情况下执行的是 /bin/echo 命令)。需要注意的是,作为参数,从标准输入中读入的“数据块”会跟随在 初始参数(initial-arguments)之后。如果你从标准输入读入的“数据块”中有些空格并非“数据块”的分隔,而是作为“数据块”的一部分出现;你需要把这个些带有空格的“数据块”整体放到单引号或双引号中,当然你也可以在那些“数据块”内部的空格前用反斜杠()进行转义。另外,标准输入中多余的空行会被忽略。

如果不使用 -n 和 -L 选项,并且没有遇到换行符的情况下,被 xargs 创建的命令的长度是“贪婪”的,直到达到系统限制的长度。而 Command 指令被调用的次数正好是标准输入中“数据块”的行数。通常情况下,命令被调用的次数是小于“数据块”的数量的;这样会在一定程度上提高命令的执行效率。有些指令可以并行执行,请参考 -P 选项。

在 Unix 系统中,文件名中是可以包含空格和换行符的,如果不对这种“特殊情况”做处理通常是会出问题的;这种在文件名中的空格和换行会被 xargs 当成“数据块”的分隔符处理。在这种情况下可以使用 -0 选项来解决问题。当使用这个-0选项时,你需要确保“数据块”之间使用null字符作为分隔符。例如:当由GNU 的 find 命令提供xargs的“标准输”时,就需要为其(find)提供 -print0 选项来达到目的。

如果有任何一次 Command 指令的调用以 255 的状态码退出,则xargs会立即停止,并会放弃此后的所有输入。错误信息会输出到“标准错误流”。

参数说明

0, --null
当 xargs 使用此选项时,null字符会被作为“数据块”的分隔符,而引号(单引用和双引号)都不在具有特殊含义(所有的字符都代表他们自己);文件结束符(EOF)也将失效。通常情况下,当“数据块”中包含空格、引号、反斜杠时适合使用此选项,GNU 中的 find 命令 使用 -print0选项时就是这种情况。

-a file, --arg-file=file
从文件中读取“数据块”,而非标准输入。如果你使用此选项,除非“标准输入”已经被重定向到 /dev/null,否则,执行命令时不会影响“标准输入”中的数据。

--delimiter=delim, -d delim
xargs 命令会以此选项指定的“特定字符”作为“数据块”的分隔符。这个“特定字符”可能是一个“普通字符”,也可能是一个C语言风格的转义字符(如:n,反斜杠后进一个十六进制或八进制数的转义字符);这些转义字符会被 printf 函数处理后再给此选项使用。此选项不支持多字节字符(也即是仅支持ASCII字符集中的字符)。使用此选项后,标准输入中的引号和反斜杠都不再是特殊字符,他们仅代表自身的字面意思。另,-d 选项还会使 文件结束符(EOF)失效,此时xargs 对待文件结束符与其他参数是完全一样的。当“数据块”中包含换行符时你也可以使用此选项来处理;虽然使用 --null 选项是更好的选择。

-E eof-str
设置“文件结束符”,xargs 在处理标准输入时,如果遇到“文件结束符”,则其后的所有输入都将被忽略。如果 -E 和 -e 选项都没有被使用,则表示在标准输入中没有字符会被当成“文件结束符”处理。

-e [eof-str], --eof[=eof-str]
此选项和 -E 选项的功能是一样一样的。请使用 -E 选项,因为他是符合 POSIX 标准的,而此选项不是。如果使用此选项时 eof-str 被省略了或 -E 和 -e 选项都没有被使用,则表示在标准输入中没有字符会被当成“文件结束符”处理。

-I replace-str
用从标准输入中得到“数据块”替换 initial-arguments 中出现的 replace-str。使用此选项后,空格(无论是否在引号中)不会作为“数据块”的分隔符,只有换行会被作为“数据块”的分隔符。使用此选项,同时意味着使用了 -x 和 -L 1 选项。

-i [replace-str], --replace[=replace-str]
此选项与 -I 选项的功能是一样的。如果 replace-str 没有被指定,则使用默认值{},此时的功能与 -I {}是一样的。这个选项已经不推荐使用,请使用 -I 选项。

-L max-lines
每个命令行最多允许有 max-lines 个非空的输入行。末尾的空白会使一个输入行在逻辑上延伸到下一行。
使用此选项,同时意味着使用了 -x 选项。

-l [max-lines], --max-lines[=max-lines]
此选项和 -L 选项的功能是一样的;不同的是此选项中的 max-lines 参数是可选的。如果 max-lines 没有被指定,则使用默认值 1 。此选项 -l 不已经不赞成被使用,请使用符合 POSIX 标准的 -L 选项代替。

-n max-args, --max-args=max-args
每个命令最多允许有 max-args 个参数。如果参数个数达不到 max-args 个,但参数的尺寸超过了限制(请参考 -s选项);此是 xargs 程序将会退出。

-P max-procs, --max-procs=max-procs
同时运行 max-procs 个进程,max-procs的默认值是1。如果 max-procs被指定为0,xargs 将会尽可能的运行多个进程。请联同-n或-L选项一起使用,否则可能只会执行一个进程。在 xargs 运行期间,你可以向他发送 SIGUSR1信号量要求增加进程,或发送SIGUSR2信号量要求减少进程。但是你无法把进程数据减少到0,因为最小值是1。xargs 不会中止命令的执行,当要求减少进程时,他会等待,只到有进程执行完成,只是在执行完成的进程想要启动其他进程时会被阻止。

-p, --interactive
交互式的运行命令,每个命令运行前都会在终端询问用户是否要执行。只有在用户响应询问时输入y或Y时才会去运行命令。打开此选项的同时,意味着-t选项也被打开了。

--process-slot-var=name
在每个子进程中分别设置环境变量name的值为不同的值。如果在某个进程中设置的值与已经存在的进程设置的值重复了,就会退出这个进程。可以用此来做负载均衡。

-r, --no-run-if-empty
如果标准输入中没有任何非空的字符,则不运行命令;默认情况下即使标准输入没有非空字符,命令也会被运行一次。这个选项是 GNU 扩展的。

-s max-chars, --max-chars=max-chars
一个命令最多包含 max-chars 个字符,包括 命令本身、initial-arguments 和标识字符结束的 nulls 字符。这个最大值是依赖于操作系统的。

--show-limits
显示操作系统对命令行长度的限制、xargs对缓冲区大小的选择和-s选项。将输入从/DEV/NULL(也许指定-如果没有空运行),如果你不想让XARGS做任何事情。

-t, --verbose
在执行命令之前输出此命令的“标准错误流”。

-x, --exit
如果超过 -s 选项指定尺寸,就退出程序。请参考 -s 选项。

--help
输出 xargs 命令的帮助信息,然后退出。

--version
输出 xargs 命令的版本号,然后退出。


最终批量删除redis的key语句如下 :

redis-cli -h host -p 6379 -a pwd -n 15 --scan --pattern "exchange*" | xargs -0 -n 5000 redis-cli -h host -a pwd -p 6379 -n 15 DEL

redis-cli参数:
-h 你的redis服务器地址
-p 端口 默认6379
-a 密码
-n 选择redis对应的db

xargs参数:
-n 按每n个为一组输出参数,如果redis的Key数量大的话可以增加此参数,否则会报错 argument list too long
-0 当key还有引号等特殊字符,加此参数可以屏蔽,使特殊字符失效,不加会报错:
xargs: unmatched single quote; by default quotes are special to xargs unless you use the -0 option

by KingFer

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/36876.html

相关文章

  • RedisPHP操作手册(纯手稿版)

    摘要:类型操作是最基本的类型,而且类型是二进制安全的。意思是的可以包含任何数据。的阻塞版本,这个版本有第三个参数用于设置阻塞时间即如果源为空,那么可以阻塞监听的时间,如果有元素了则执行操作。 String 类型操作 string是redis最基本的类型,而且string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 $redis->set...

    dingding199389 评论0 收藏0
  • RedisPHP操作手册(纯手稿版)

    摘要:类型操作是最基本的类型,而且类型是二进制安全的。意思是的可以包含任何数据。的阻塞版本,这个版本有第三个参数用于设置阻塞时间即如果源为空,那么可以阻塞监听的时间,如果有元素了则执行操作。 String 类型操作 string是redis最基本的类型,而且string类型是二进制安全的。意思是redis的string可以包含任何数据。比如jpg图片或者序列化的对象 $redis->set...

    Travis 评论0 收藏0
  • redis学习笔记(二)--Redis API理解与使用

    摘要:本身就是型,哈希结构相当于在里又套了一层型数据。计算的字符串长度内部编码压缩列表当哈希类型元素个数小于配置默认个,同时所有值小于配置默认字节时,会启用。哈希表列表基本概念列表是简单的字符串列表,按照插入顺序排序。 字符串 通用命令 查看所有key > key * 遍历所有key 计算键总数 > dbsize 检查键是否存在 > exists key 存在返回1,不存在返回0 删除键 >...

    fantix 评论0 收藏0
  • Redis基本数据结构及基本命令详解

    摘要:此文主要讲解的基本数据结构以及使用客户端的基本操作命令。对于哈希集中不存在的每个字段,返回值,因为不存在的被认为是一个空的哈希集。对一个不存在的执行将返回一个只含有值的列表返回返回指定的哈希集中所有的字段和值。 redis是一个key-value存储系统。和Memcached类似,它支持存储的value类型相对更多,包括string(字符串)、list(链表)、set(集合)、zset...

    Turbo 评论0 收藏0
  • Python 数据库骚操作 -- Redis

    摘要:支持五种数据类型字符串,哈希,列表,集合及有序集合。工具首先介绍一款的工具,初学用这个来查看数据真的很爽。可以即时看到数据的增删改查,不用操作命令行来查看。不存在时,不会自动创建。的骚操作就介绍到这里,后面会继续写的骚操作。 目录 前言 Redis GUI 工具 Redis 遇上 Docker Redis string Redis hash Redis list Redis set ...

    xiongzenghui 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<