定时自动删除redis key

Posted wzy0623

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了定时自动删除redis key相关的知识,希望对你有一定的参考价值。

目录

1. 背景描述

2. 实现脚本

3. 自动执行


1. 背景描述

        使用redis存储群发消息。当初匆忙上线,设计上有两个主要问题:一是在每个userid的key中存储消息体,从数据库的角度看,存在大量的数据冗余,占用大量存储空间。二是不设置key的过期时间,使得redis像貔貅一样只进不出,不断膨胀。

        由于对用户的群发消息量很大,使得redis几天就内存报警。开始时使用单实例redis,遇到报警就增加maxmemory配置。后来将单实例进行拆分,按照userid取模4,拆分成4个redis实例。但结果是治标不治本,依旧撑不了几天,架不住一个劲地狂发消息啊。不得已只能采用定期删除未读消息的方案来弥补设计缺陷。

2. 实现脚本

delmsg.sh内容如下:

#!/bin/bash

cd ~/delmsg/

# 已处理的最大logid,首次为0
max_logid=`cat max_logid.txt`

# 从mysql导出三天前的数据,这部分可以删除。mod4列用来标识userid的模数。
mysql -u user1 -p123456 -h 10.10.10.1 -P3306 -D db1 -N -e "
select @dt:=current_date;
select logid, userid, msgorder, 
       case when mod(userid,4)=0 then 'mod4_0'
            when mod(userid,4)=1 then 'mod4_1'
            when mod(userid,4)=2 then 'mod4_2'
            else 'mod4_3'
       end mod4
  from batch_system_msg_user_msgorder_log 
 where yearMonth=year(@dt)* 100 + month(@dt)
   and createTime < date_sub(@dt, interval 3 day)
   and logid > $max_logid order by logid" > yushu.txt


######## 处理mod4_0(20007端口的redis实例)########

# 生成mod4_0的redis命令文件,每个文件不超过50000行,避免报redis每秒命令数超限警告
grep mod4_0 yushu.txt | awk '{print "zremrangebyscore UnReadMessageEx_"$2 " " $3 " " $3}' | split -l 50000 -d -a 5 - yushu0_

# 由于可能发生自动主从redis切换,需要从哨兵获取当前20007端口的master ip
master=`/home/redis/redis-5.0.3/src/redis-cli -p 30001 info | grep 20007 | awk -F, {'print $3'} | awk -F= {'print $2'} | awk -F: {'print $1'}`

# 删除消息。使用--pipe方式逐个处理split生成的命令文件,每个文件处理后sleep 1秒用于缓解负载。
ls -l yushu0_* | awk {'print "cat " $9 " | /home/redis/redis-5.0.3/src/redis-cli -h '$master' -p 20007 -a 123456 -n 1 --pipe; sleep 1;"'} > yushu0.sh
chmod 755 yushu0.sh
./yushu0.sh


######## 处理mod4_1(20006端口的redis实例)########
grep mod4_1 yushu.txt | awk '{print "zremrangebyscore UnReadMessageEx_"$2 " " $3 " " $3}' | split -l 50000 -d -a 5 - yushu1_

master=`/home/redis/redis-5.0.3/src/redis-cli -p 30001 info | grep 20006 | awk -F, {'print $3'} | awk -F= {'print $2'} | awk -F: {'print $1'}`

ls -l yushu1_* | awk {'print "cat " $9 " | /home/redis/redis-5.0.3/src/redis-cli -h '$master' -p 20006 -a 123456 -n 1 --pipe; sleep 1;"'} > yushu1.sh
chmod 755 yushu1.sh
./yushu1.sh


######## 处理mod4_2(20015端口的redis实例) ########
grep mod4_2 yushu.txt | awk '{print "zremrangebyscore UnReadMessageEx_"$2 " " $3 " " $3}' | split -l 50000 -d -a 5 - yushu2_

master=`/home/redis/redis-5.0.3/src/redis-cli -p 30001 info | grep 20015 | awk -F, {'print $3'} | awk -F= {'print $2'} | awk -F: {'print $1'}`

ls -l yushu2_* | awk {'print "cat " $9 " | /home/redis/redis-5.0.3/src/redis-cli -h '$master' -p 20015 -a 123456 -n 1 --pipe; sleep 1;"'} > yushu2.sh
chmod 755 yushu2.sh
./yushu2.sh


######## 处理mod4_3(20014端口的redis实例) ########
grep mod4_3 yushu.txt | awk '{print "zremrangebyscore UnReadMessageEx_"$2 " " $3 " " $3}' | split -l 50000 -d -a 5 - yushu3_

master=`/home/redis/redis-5.0.3/src/redis-cli -p 30001 info | grep 20014 | awk -F, {'print $3'} | awk -F= {'print $2'} | awk -F: {'print $1'}`

ls -l yushu3_* | awk {'print "cat " $9 " | /home/redis/redis-5.0.3/src/redis-cli -h '$master' -p 20014 -a 123456 -n 1 --pipe; sleep 1;"'} > yushu3.sh
chmod 755 yushu3.sh
./yushu3.sh

# 更新已处理的最大logid
tail -1 yushu.txt | awk '{print $1}' > max_logid.txt

# 清理文件
rm -f yushu0_* yushu1_* yushu2_* yushu3_*

3. 自动执行

在crontab中增加项:

0 4 * * * /home/redis/delmsg/delmsg.sh > /home/redis/delmsg/delmsg.log 2>&1

 

以上是关于定时自动删除redis key的主要内容,如果未能解决你的问题,请参考以下文章

redis的过期策略以及内存淘汰机制

redis的过期删除策略

Redis Key过期淘汰策略

redis 删除策略

redis 删除策略

Redis的key过期处理策略