百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

redis big key分析及shell删除(redis删除hashkey)

nanshan 2024-11-06 11:15 10 浏览 0 评论

目前coids 8个master节点8个slave节点,把两台机器600G的内存吃完了,有点夸张。业务上的人只管用,并没有过多关注redis的健康状况,经过分析后发现有很多的垃圾数据。


1、153上 节点6379 - 6386上每个几点大约有1300 - 1400W个key。


?


也可以通过redis desktop manager 连接单节点来查看。


?


可以看到这些key的数量是动态变化的。是因为有的key设定了过期时间代表它已经过期了,关于设定了expire的key何时释放空间?这篇文章中 内存溢出控制策略 有详细阐述。


2、查找big key,redis 提供了一个bigkeys的命令。


得到的结果不一定准确,是因为其统计key的数据规模并不是占用内存最大的key。


bigkeys的原理,非常简单,通过scan命令遍历,各种不同数据结构的key,分别通过不同的命令得到最大的key:


  • 如果是string结构,通过strlen判断;
  • 如果是list结构,通过llen判断;
  • 如果是hash结构,通过hlen判断;
  • 如果是set结构,通过scard判断;
  • 如果是sorted set结构,通过zcard判断。


redis-cli  -p 6380 --bigkeys

[root@P1QMSPL2RTM01 ~]# redis-cli  -p 6380 --bigkeys

# Scanning the entire keyspace to find biggest keys as well as
# average sizes per key type.  You can use -i 0.1 to sleep 0.1 sec
# per 100 SCAN commands (not usually needed).
......
-------- summary -------

Sampled 13788262 keys in the keyspace!
Total key length in bytes is 376277646 (avg len 27.29)

Biggest string found 'RPT_20200327044033141' has 15102 bytes
Biggest   list found 'opehis:A196E06WBE' has 1058 items
Biggest   hash found 'HMS:ERROR:HMS_ERROR2' has 2393 fields
Biggest   zset found 'history:L6400' has 4736943 members

12788812 strings with 367806347 bytes (92.75% of keys, avg size 28.76)
915321 lists with 8590020 items (06.64% of keys, avg size 9.38)
0 sets with 0 members (00.00% of keys, avg size 0.00)
4397 hashs with 30777 fields (00.03% of keys, avg size 7.00)
79732 zsets with 98114217 members (00.58% of keys, avg size 1230.55)



#!/bin/bash
#/usr/local/codis/src/github.com/CodisLabs/codis/bin/redis-cli  -p 6379 -i 0.1 --bigkeys >/home/scripts/6379_153.log
#sleep 40m
#/usr/local/codis/src/github.com/CodisLabs/codis/bin/redis-cli  -p 6380 -i 0.1 --bigkeys >/home/scripts/6380_153.log
#sleep 40m
#/usr/local/codis/src/github.com/CodisLabs/codis/bin/redis-cli  -p 6381 -i 0.1 --bigkeys >/home/scripts/6381_153.log
#sleep 40m
#/usr/local/codis/src/github.com/CodisLabs/codis/bin/redis-cli  -p 6382 -i 0.1 --bigkeys >/home/scripts/6382_153.log
#sleep 40m
/usr/local/codis/src/github.com/CodisLabs/codis/bin/redis-cli  -p 6383 -i 0.1 --bigkeys >/home/scripts/6383_153.log
sleep 40m
/usr/local/codis/src/github.com/CodisLabs/codis/bin/redis-cli  -p 6384 -i 0.1 --bigkeys >/home/scripts/6384_153.log
sleep 40m
/usr/local/codis/src/github.com/CodisLabs/codis/bin/redis-cli  -p 6385 -i 0.1 --bigkeys >/home/scripts/6385_153.log
sleep 40m
/usr/local/codis/src/github.com/CodisLabs/codis/bin/redis-cli  -p 6386 -i 0.1 --bigkeys >/home/scripts/6386_153.log



事实上并不用在master上做这个操作,因为master和slave上的数据是同步的,在master上执行此命令可能会严重阻塞client的写命令,尽管使用了-i 0.1 这个参数。


尽管是统计某个key的数据规模,但是看到这些数据有点夸张,有的key竟然还是19年6月的甚至更早,history:L6400 竟然能有470W个value,而这仅仅是一个站点的数据。


事实上,是有一只删除redis 旧key的程序,可是通过分析其逻辑是典型的顾头不顾尾。那当务之急就是为何释放redis的内存,因为redis服务器的内存使用率一直高达99%。


删除当然是找数据最多的,这个key是 zset类型。用了几个小时学习了sorted set的基本使用方法。


删除的逻辑大致是:遍历站点list,拼凑history:ope这个key,然后用zremrangebyscore删除,score根据实际业务来决定。


删除脚本如下


#!/bin/bash
#/usr/local/codis/src/github.com/CodisLabs/codis/bin/redis-cli  -p 6379 -i 0.1 --bigkeys >/home/scripts/6379_153.log
#redis-cli -p 6385 zscan history:L7100 0  match '*:*:*:*:*:**M' count 10000 >history_ope.log
#redis-cli -p 6385 zrangebyscore history:L7100 -inf +inf WITHSCORES > history_L7100.log
#sleep 5s

#2017-01-01 00:00:00 ->
#fromTime='1483200000'
#2018-12-31 23:59:59 ->
#toTime='1546271999'

#2018-12-31 23:59:59 ->
fromTime='1546271999'
#2019/08/31 23:59:59 
toTime='1567267199'

logname='del_19_1-8.log'
bkname='del_19_1-8.bk'

TIME=$(date '+%Y%m%d%H%M%S')
count=0
#path='/home/scripts/test/opeList.txt'
path='/home/scripts/test/delete/opeList.txt'
while read -r ope
 do
#for ope in $(cat ${path})  //在执行删除的时候遇到过效能问题,例如删除result:glass这个key的时候每次读取5-7W行数据然后进行后面的逻辑发现需要2300s,如果减少数据量到2W速度能到100s,这个差距由点大,用for循环每次读一行比从while缓存中读快吗?  改天测试一下
#do
var1=$(/usr/local/codis/src/github.com/CodisLabs/codis/bin/redis-cli -p 19000 zrangebyscore history:${ope} $fromTime $toTime|wc -l)

# zcard 统计数量可考虑使用该命令计算
#count=$($[count] + $[var1])
count=`expr $count + $var1`
#echo $var1

/usr/local/codis/src/github.com/CodisLabs/codis/bin/redis-cli -p 19000 zremrangebyscore history:${ope} $fromTime $toTime

sleep 1s


echo "$TIME /usr/local/codis/src/github.com/CodisLabs/codis/bin/redis-cli -p 19000 zremrangebyscore history:${ope} $fromTime $toTime " >> /home/scripts/test/delete/$bkname

echo "$TIME ope: $ope,delQty: $var1 " >> /home/scripts/test/delete/$logname
#test
#redis-cli -p 6385 zscan history:${ope} 0  match '*:*:*:*:*:**M' count 1000 > history_6383_${ope}.log
#done
done < opeList.txt
echo "totalQty: $count" >> /home/scripts/test/delete/$logname



删除数据量统计


时间

17年- 18年

19年1-6月

Value数量

约1000W

36970313

Key数量

211

内存

1.6GB

7.2GB


这总算是解了燃眉之急,至少redis能撑2-5天。毕竟不是长久之计。


内存使用一个脚本估算出来的:


精确评估 history:ope 的大小

概述:在测试环境,将history:ope zadd 10000笔, 打印前后的内存变化,同时根据模型计算,比较两者的差距。
Shell 脚本如下

#!/bin/sh
key="history:A3850"
old_memory=`/usr/local/bin/redis-cli -h 0 -p 6380 info|grep used_memory:|awk -F: '{printf "%d", $2}'`
echo "before test, memory used: $old_memory"
#for((i=100; i<900; i++))
#do
for((j=1483200000; j<1483210000; j++))
do
/usr/local/bin/redis-cli -h 0 -p 6380 zadd $key $j AOIH0200:AOIH0200:A3850E495A1:A1495A1ANK1:A183A00VN01:$j:M > /dev/null
done
sleep 0.5
#done
new_memory=`/usr/local/bin/redis-cli -h 0 -p 6380 info|grep used_memory:|awk -F: '{printf "%d", $2}'`
echo "after test, memory used: $new_memory"
let difference=new_memory-old_memory
echo "difference is: $difference"

[root@gptest01 redis]# ./evaluateHisOpeMem.sh 
before test, memory used: 415131248
after test, memory used: 417395400
difference is: 2264152



一个key的写入10000笔数据,需要占用2.16MB
故4000W的value规模可以释放8.5GB的数据


前期用模型估算出来的大小为7G左右。


Value 长度 67byte
共7段
平均每段 = (8 + 8 + 11 + 11 + 11 + 10 + 1)/7 = 8.58byte≈9byte


?




参考:


https://www.jianshu.com/p/5c5dc0d7d776
http://doc.redisfans.com/index.html


3、利用rdb tool来讲dump导出写入mysql 通过下sql 的方式查redis数据。


rdb -c memory -l 5 dump.rdb


找出前5大key。


[root@P1QMSPL2RTM01 redis]# rdb -c memory -l 5 dump.rdb 
database,type,key,size_in_bytes,encoding,num_elements,len_largest_element,expiry
WARNING: python-lzf package NOT detected. Parsing dump file will be very slow unless you install it. To install, run the following command:

pip install python-lzf


后来运维人员装好了rdb tool,经过分析原来result:glassId才是终极大boss。


至此,才算真正意义上找到了”bigkeys”,这才是占用reids最大的内存了。


在处理这次事故中,发现目前架构是主从读写分离的架构,在重放slave的aof文件时发生了瞬时读取不到key的情况,着实让人操心。关于此请参照我写的另外一篇。


-------------update 2020年4月26日08:44:45 -----------------------


还有一点是非常奇怪的现象:


旧的数据清理完了之后发现一个奇怪的现象,6385节点的内存交其他节点多10GB,这是很奇怪的,通过codis-proxy写入key时会根据冗余校验算法分配到每一个slot上,理论上来说数据倾斜不会这么严重。


?


对该节点重新做了bgsave ,分析dump之后,发现更奇怪的事情, 某些过期数据残存在6385上,透过proxy竟然访问不到,这是为何呢???


[root@P1PL2RTM01 redis]# redis-cli -p 19000 zrange result:A18BR04NAY 0 -1
(empty list or set)
You have new mail in /var/spool/mail/root
[root@P1PL2RTM01 redis]# redis-cli -p 6385 zrange result:A18BR04NAY 0 -1
1) "{\"actualEqptId\":\"MSPU0200\",\"defectCnt\":0,\"glassId\":\"A18BR04NAY\",\"ifPreProcess\":true,\"ooc\":false,\"oos\":false,\"panelCnt\":8,\"processEndTime\":1543355980,\"ruleSeqId\":3277}"
2) "{\"actualEqptId\":\"MSPU0200\",\"defectCnt\":2,\"glassId\":\"A18BR04NAY\",\"ifPreProcess\":true,\"ooc\":false,\"oos\":false,\"panelCnt\":8,\"processEndTime\":1543355980,\"ruleSeqId\":3298}"



针对目前的怪现象:


codisproxy把某个key写在哪个slot了?这些信息会记录在zk吗?client现在想读刚才写入的数据 应该从哪个slot读呢?


是不是可以从这几个方面入手呢?


更详尽的内容请参考:


https://redis.io/topics/rediscli#scanning-for-big-keys


源代码分析


https://blog.csdn.net/aoerqileng/article/details/86687499

?


相关推荐

教你一个解决手机卡顿的方法(10秒解决手机卡顿问题)

我们的手机天天刷头条,看视频,用了一阶段时间以后,就时不时的发生卡顿现象。昨天我的手机就发现了这个问题。友友们,你们遇到过这样的问题吗?你们都是怎样解决的?我看了一眼我的粉丝情况,头条君给我分析的很精...

手机视频缓存清理,3步彻底清空,告别卡顿

在我们使用手机观看视频的过程中,经常会产生大量的缓存垃圾,这些垃圾文件不仅占用了手机的存储空间,还可能导致手机卡顿和运行缓慢。然而,你知道如何彻底清空手机的视频缓存,让手机恢复流畅的使用体验吗?在本文...

关手机这个开关,轻松提升流畅度!

关闭手机这个开关,跟新买的一样流畅。手机不要再清理垃圾了,只要关闭这个开关,手机就会和新买的差不多,丝滑流畅不卡顿。其实抖音里就隐藏着一个小开关,每天刷过的视频都会保存在手机里,如果一直不清理,手机就...

如何清理今日头条和西瓜视频的内存,让手机流畅不卡顿?

对于老年人而言,今日头条和西瓜视频能带来丰富的资讯与娱乐。然而,随着使用时间的增加,这些应用会占用大量手机内存,致使手机运行卡顿。那该如何解决呢?接下来,我将用最简单易懂的方式教老年人清理今日头条和西...

视频在线如何转换格式?好用不卡顿的三种转换办法

转换视频格式目前来说已经是很熟练的操作了,但是还有些用户可能还是不知道,小编今天就特意给大家带来一些小众才知道的转换教程,让新手也能快速的上手去转换视频格式,以后获取到视频就不怕内容丢失了,视频的格式...

如何把视频慢放处理?这几个慢放方法记得收藏

如何把视频慢放处理?如果你想让视频慢放,可能是因为你想放慢一些精彩的瞬间,或者你想制作一个慢动作视频。在这篇文章中,我们将介绍一些调速方法,这些方法可以有效地调整视频速度,一起来学习一下吧。方法一:使...

如何清理看过的视频,释放垃圾,让手机更流畅?

现在谁的手机上没几个短视频平台,无聊时就会刷别人的视频。可您知道吗?我们看过的内容都会被自动保存在手机里,而且很耗内存。如果长时间不释放,手机就会出现各种问题,其中最突出的就是反应慢。相信很多老年人的...

手机掉帧是怎么回事?刷视频的时候经常掉帧卡顿

手机掉帧是指在运行应用或视频时,画面出现卡顿、不流畅的现象,通常由硬件性能不足、软件优化不佳、内存占用过高、网络问题或设备过热等因素引起。尤其是在刷视频时,掉帧问题可能更为明显,以下是具体原因及解决方...

拍视频画面卡顿不流畅,原来是相机设置错误 #短视频拍摄

拍摄视频时,应该选择哪种快门速度?许多新手朋友可能会认为,快门速度越高,画面就越清晰,实则不然。因为拍摄视频时,需要考虑一个问题,即动态模糊。例如,如果设置为24帧/秒,那么每秒钟会拍摄24张图片。如...

手机卡顿最大原因#视频太卡怎么变流畅

抖音这几个开关是手机卡顿的最大原因。你是不是也会经常遇到刷视频的时候,打开一个视频之后老半天还在那转着圈圈,总觉得手机没有之前流畅了。这就说明你的手机占用的内存太多了,导致手机卡顿,使用不流畅。使用手...

为啥你家的玩游戏和刷视频经常性的会卡,那是你不懂这些小妙招

本内容来源于@什么值得买APP,观点仅代表作者本人|作者:暴走的黄小猪说到网速有不少的值友都有一个共同点,那就是“卡”,那是你根本没体验过啥叫真正的网速啊,全屋零四条网络报表也花不了几个钱你们的方法...

电脑看视频卡顿有什么解决方法?(电脑看视频画面卡顿是什么原因)

电脑看视频卡顿的原因可能多种多样,包括硬件性能不足、网络问题、软件设置不当等。以下是一些常见的解决方法,帮助你改善视频播放的流畅度:一、硬件方面1.检查硬件性能:如果电脑配置较低,尤其是CPU、内存或...

手机Wi-Fi满格但视频卡顿,你需要这样解决

累了一天的打工人回家拿出手机准备玩玩游戏,看看电影时,发现网络异常卡顿,但手机又显示Wi-Fi信号满格,当咱们遇到此类问题时,这些动作能让网络恢复正常,方法如下。一、重启路由器和光猫很多家庭在安装好路...

视频越刷越卡?原来是路由器开启了这个功能,关闭方法来了

应该很多小伙伴都有过类似的经历,就是在家里长时间刷视频或者看剧的时候,网速好像会越来越慢,视频总是要加载。手机本身可能是一部分原因,但路由器也会影响,你知道吗?当我们在刷视频的,路由器会悄悄地开启大量...

一招解决视频卡顿的问题,改变发布渠道后,结果香了

最近一段时间拍了很多美景视频,编辑发布到头条后,有时一直显示在缓冲,播放不了,有时打开断断续续的,老是卡顿。导致的后果是:要么展现量很低,要么阅读量寥寥无几,这让我非常苦恼。所以再发布作品时,我只好文...

取消回复欢迎 发表评论: