当我们需要批量删除redis的key时,很多时候都是依赖redis的client加上linux的xargs来做。
比较常见的像是,通过keys匹配数据,然后进行del。
相应的删除语句就是:
redis-cli -h 地址 -p 6379 -a 密码 keys "匹配内容" | xargs ./redis-cli -h 地址 -p 6379 -a 密码 del
但是如果是在线上服务器里,假设是百万、千万个key里面去进行keys匹配,很明显会引起阻塞可能CPU使用率就会上升很快。
如何在不影响线上环境使用的前提下进行操作,很自然的想到的就是通过使用scan来提到keys的匹配扫描。
redis-cli -h 地址 -a 密码 -n 操作DB scan 0 match "匹配内容" count 扫描数量 | xargs -t redis-cli -h 地址 -a 密码 -n 操作DB del
但是scan命令的这个游标,只靠这行脚本可能就扫不完全整个库了。
看到有些文章是通过如下形式进行操作:
redis-cli --scan --pattern “testkey-*” | xargs -L 1000 redis-cli del
但是xargs -L 1000似乎并不能很好的使用scan。所扫描的结果也不能发挥scan的作用。
我们知道scan命令会返回2个值。第一个为游标移动后的新位置,第二个是匹配到的key值。
第一个值为0时说明扫描完成了一遍。
经过尝试,最后选择用shell来处理。具体代码参考如下:
第一个返回值存入游标变量作为下一次的扫描入参。
第二个返回值是需要删除的key值,用数组保存。
#!/bin/bash
redis_url=地址
redis_pass=密码
redis_db=操作DB
scan_patten=匹配字符串
scan_count=扫描数量
yb=0
while 1>0
do
count=0
declare -a array
declare -a result
for i in `redis-cli -h $redis_url -a $redis_pass -n $redis_db scan $yb match $scan_patten count $scan_count`;do
result[${count}]=${i}
count=$(expr ${count} + 1)
done
yb=${result[0]}
for j in ${!result[@]}
do
if [ $j -gt 0 ]
then echo ${result[$j]}
array[${count}]=${result[$j]}
fi
done
if [ ${#array[@]} -gt 0 ]
then
echo ${array[@]} | xargs -t redis-cli -h $redis_url -a $redis_pass -n $redis_db del
fi
if [ $yb -eq 0 ]
then break
fi
unset result
unset array
done
测试有效,以下是返回结果:
![在这里插入图片描述](https://img-blog.csdnimg.cn/f4da2f76225647189371d45857d4510d.png?x-oss-process=image/watermark,type_ZHJvaWRzYW5zZmFsbGJhY2s,shadow_50,text_Q1NETiBA5bCR5a6k5a2m57yW56iL,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)
Warning: Using a password with ‘-a’ or ‘-u’ option on the command line interface may not be safe.
这行命令是redis-cli时提示不要在控制台使用-u -a 不安全,防范密码泄漏的风险。