redis expire方式设置缓存时间的坑

最近入职后一直很忙,今天国庆值班,把前段时间遇到的问题抛出来总结一下。

1、背景

在项目中需要记录用户的相关状态,这些状态会在一天内清除,且又不止0/1这两种状态,于是考虑将其放在一个hash的key当中。

但是redis对于hash类型,并没有提供直接设置超时时间的支持,于是设计采用expire一个key的过期的时间方式来实现当日过期。

2、问题

通过观察发现,隔天的数据,在共用一个key的情况下并没有如预估的一样过期。

3、原因

因为所有的hash都共用一个key,比如hermes:newest,这样当设置了hash的field之后,会紧接着通过expire设置过期时间,如

// 代码经过改写过,大意就是这样,把公司的包替换了
template.execute(jedis -> {
    Pipeline pipeline = bedis.pipelined();
    pipeline.hset(keyHash, String.valueOf(uid), JsonUtils.toJson(userInfo));
    pipeline.expire(keyHash, seconds);
    return pipeline.sync(false);
});

A、过期时间是通过计算到下一天0点时的剩余时间。

B、expire的删除方式为定期删除+懒删除,不一定会立即删除掉这个key。每次从数据库获取key的时候去检查是否过期,若过期,则删除,返回null。或者定期扫描去删除。

这样一来,当11点59分59秒设置了失效时间为1秒时,再接下来00点00分00秒时,设置的失效时间并不是0秒,而是到后一天的24小时,所以会在删除前,直接覆盖掉之前的key的过期时间,使前一天的field结果不被删除。

4、解决方法

A、采用定时任务,每天0点对这个key做一次主动删除操作。

B、hash的key上带有时间标记,如加上每一天,这样就会使得key的过期时间不被覆盖,到了定时删除的时间,前一天的key自然会被删除。

C、采用setx的方式来存储key-value

目前在项目中采用的为B方法。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值