分析的过程都是小伙伴做的,我只是记录下。
现象
12号钉钉群告警,某个实例有内存使用率的问题。
分析
实例内存增长,从11号开始的。
那就看 10号跟12号的rdb。看看期间的增长情况(期间每个实例都增长了1个G)。
处理过程
- 下载 rdb文件
wget -O 9100.rdb http://rdsbakxxx. _data_201909100xxx.rdb
rdb -c memory 9120.rdb > 9120.csv
rdb -c memory 9100.rdb > 9100.csv
- 分析哪些key出现的频次比较高。
cat 9120.csv |awk -F':' '{if($2!="") print $2}' | sort | uniq -c| sort -n -r | head -n 10
找出来type这个关键词出现次数最多。紧接着看包含type的key是否为必要删除的key。
- 找到业务程序中的包含type的key ‘user:type:user:info:’,看10号跟12号,的内存情况。
cat 9100.csv| grep 'user:type:user:info:' | awk -F' ' 'BEGIN{a=0}{if($2!="") a+=$2}END{print a/1024/1024/1024}'
cat 9120.csv| grep 'user:type:user:info:' | awk -F' ' 'BEGIN{a=0}{if($2!="") a+=$2}END{print a/1024/1024/1024}'
经对比,12号比10号多了0.8G。于是找到了增长元凶(每个实例增长了1个G)
- 删除这些key。
经分析,该key是可以删除的(缓存用户信息)。另外看到程序中缓存时间为100天,后改成了1个小时。
把12号的rdb中要删除的key放到一个文件中。
rdb -c justkeys --db 0 --key "user:type:device:info:*" 912.rdb > deviceKey.txt
5.写删除脚本
脚本内容参考。
public function run()
{
global $argv;
$fileName = $argv[1] ?? 0;
if (empty($fileName)) {
var_dump('没有文件');
return ;
}
$redeis = Redis::getInstance('xxxxx');
$count = 0;
$handle = fopen ($fileName, "r");
$successCount = 0;
while (!feof ($handle))
{
$buffer = fgets($handle, 4096);
$key = trim($buffer);
if (empty($key)) {
continue;
}
$result = $redeis->del($key);
$count++;
if ($result) {
var_dump('success:'.$key);
$successCount++;
} else {
var_dump('error:'. $key);
}
if ($count % 100000 === 0) {
var_dump('10万个,睡眠5秒钟');
sleep(5);
}
}
if ($successCount == $count) {
var_dump('删除完毕');
}
fclose ($handle);
}
找台线上环境的机器执行。(最好rdb文件下载到那台机器,不然还要用其他方式挪过去,scp或者ftp什么的)
php /xxxxx/clear-redis-deviceid-cache.php /xxxxxx/deviceKey.txt >> result.txt
ps.原本的思路是找大key 的(也是同样的类似的思路)。但是找到的都是必要的key,都不能删。后来的思路改成了哪些特征的key出现的次数高。
网友评论