由于早期使用redis时,没有指定key过期时间,导致大量内存浪费,排查修改合理指定过期时间,历史数据的清理比我想象中有难度
参考阿里云开发者社区文章,使用Linux的xargs命令以及keys+del批量删除
- begin
-
- sudo redis-cli -h localhost -p 6379 -a password keys "tryCurrentWorkerSwitch*" | xargs sudo redis-cli -h localhost -p 6379 -a password del
-
- end
此方案有两个问题:
参考redis官方手册,使用scan命令查找key不会阻塞
- begin
-
- sudo redis-cli -h localhost -p 6379 -a password scan 0 match "tryCurrentWorkerSwitch*" count 1000 | xargs sudo redis-cli -h localhost -p 6379 -a password del
-
- end
此方案的问题在于count小的话要执行次数太多,需要脚本化循环处理才有可能实施,count大的话xargs拼接del命令的时候也会超出参数的长度限制
参考网友现成的方案,考虑key多执行时间长以及日志较多,不挂起执行脚本实现批量删除,并删除不挂起执行日志文件防止日志文件过大。
scantodel.sh内容:
- #!/bin/bash
-
- if [ "$#" -lt 3 ]
- then
- echo "Scan keys in Redis matching a pattern using SCAN (safe version of KEYS)"
- echo "Usage: $0 [pattern] <host> [port] [database] [count] [second]"
- exit 1
- fi
- pattern=${1:-}
- host=${2:-}
- port=${3:-6379}
- database=${4:-0}
- count=${5:-5000}
- second=${6:-1}
-
- if [ ! -n "$pattern" ] ;then
- echo "pattern shoud not be empty!"
- fi
-
- cursor=-1
-
- keys=''
-
- while [ $cursor -ne 0 ]; do
-
- if [ $cursor -eq -1 ]
- then
- cursor=0
- fi
-
- reply=`redis-cli -h "$host" -p "$port" -n "$database" SCAN $cursor MATCH $pattern COUNT $count`
-
- cursor=`expr "$reply" : '\([0-9]*[0-9 ]\)'`
-
- keys=${reply#[0-9]*[[:space:]]}
-
- redis-cli -h "$host" -p "$port" -n "$database" DEL $keys
-
- sleep $second
-
- done
执行脚本
- begin
-
- sudo nohup sh scantodel.sh *pattern* 127.0.0.1 6379 0 5000 1
-
- rm -f nohup.out
-
- end
除了前面提到的没有设置过期时间,还有个问题是这种量级的key。千万级别的key听起来很牛的样子,实际憨得不行,完全可以冗余hash对key进行归类,当然也需要避免一个hash元素过大,需要合理的设计key及其结构。