需求场景
在业务中有些数据因为历史原因用的hash
结构存储数据,但是后期需求要求其中某个field
需要按照一些规则去过期,这个时候原来的逻辑懒得改,可以利用redis
的zset
或者mq
的延时队列去做过期设置.
方案一使用redis的zset配置定时任务
捞个图
demo需要清缓存的redis
的hash
结构如下
然后我们再每次往agent
这个hash
结构存储数据的时候,同时向agentexpire
为key
的zset
数据结构存储一份数据(在存数据的时候可以在当前时间上增加过期时间),这个数据的key
是hash
结构中的field
的值,value
是过期时间戳(毫秒级
)
如下图所示:
然后用一个定时任务(我这里用的xxl-job,大家可以自己选择)定时去扫描这个zset
里面score
小于当前时间的元素,也就是使用zset
的rangebyscore
命令:
上面在向zset
中存数据的时候已经增加了过期时间,那么当时间小于当前时间时就过期了,代表hash
中对应field
的数据要被delete
long currenttimemillis = system.currenttimemillis(); //扫描key为agentexpire的zset中时间在 0~currenttimemillis当前时间范围内的数据 set<string> keys = redistemplate.opsforzset().rangebyscore("agentexpire", 0, currenttimemillis); //然后遍历删除即可 for (string key : keys) { boolean hashresult = stringredistemplate.opsforhash().haskey("xxxxxx", key); if(hashresult){ stringredistemplate.opsforhash().delete(recommenkey, key); stringredistemplate.opsforzset().remove(selectionrecommenaspect.selectionrecommendzset, key); } }
方案二使用mq延时队列
延时队列的配置可以参考我另一篇文章
在延时队列消费者处增加上述过期代码即可
long currenttimemillis = system.currenttimemillis(); set<string> expirekeys = //扫描key为agentexpire的zset中时间在 0~currenttimemillis当前时间范围内的数据 redistemplate.opsforzset().rangebyscore("agentexpire", 0, currenttimemillis);
综上
使用zset
的话开发量少,但是定时job
一直刷容易浪费资源,mq延时队列
更精确
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持七九推。
发表评论