请教一个 Redis 过期时间的问题

讨论 未结 21 30
7911364440
7911364440 会员 2022年9月7日 03:29 发表
<p>程序的逻辑是这样的: 有一个定时任务在执行前会判断 redis 中是否存在数据,如果存在则不执行,如果不存在继续执行,然后在 Redis 中新增数据并且把定时任务间隔时间作为数据的过期时间。</p> <p>正常情况下,下一次任务执行前 Redis 中一定是没有数据的,但是实际上任务第二次执行的时候 Redis 中的数据总是不为空,后续似乎一切都正常。</p> <p>Redis 扫描过期数据的间隔是 50ms ,也尝试过 timeout = timeout-50 ,但第二次任务执行时 redis 还是不为空!!!</p> <p><strong>想问下有没有遇到过类似情况的大佬,麻烦指点下!!!</strong></p> <p>start 是任务开始时的时间戳,timeout 是计算出来的任务间隔时间,也是 redis 的过期时间</p> <hr> <h2>start: 1662520720050 timeout: 4950 foo task execute -- 正常执行</h2> <h2>start: 1662520725006 timeout: 4994 redis not empty -- 这里第二次总是不为空</h2> <h2>start: 1662520730013 timeout: 4987 foo task execute</h2> <h2>start: 1662520735004 timeout: 4996 foo task execute</h2> <h2>start: 1662520740001 timeout: 4999 foo task execute</h2> <h2>start: 1662520745010 timeout: 4989 foo task execute</h2> <h2>start: 1662520750005 timeout: 4995 foo task execute</h2> <h2>start: 1662520755004 timeout: 4996 foo task execute</h2> <p>start: 1662520760015 timeout: 4985 foo task execute</p>
收藏(0)  分享
相关标签: 灌水交流
注意:本文归作者所有,未经作者允许,不得转载
21个回复
  • kailyn
    2022年9月7日 03:58
    过期时间是不严格的,并不是你设置多久,多后就真的过期。好像是有个专门负责处理过期 key 的线程,类似于按照一定时间轮询遍历 key ,判断过期了再删除。
    0 0
  • zmal
    2022年9月7日 03:58
    定时任务的时间间隔没那么准,和 redis 没啥关系。你这个方案问题也蛮多的,redis 执行延迟、定时任务阻塞都会导致不可靠。
    0 0
  • zmal
    2022年9月7日 03:58
    1L 说的不准确,redis 的定期删除和惰性删除能保证在第二次 get 时确定是否删除。但 redis 过期是在 redis 服务写入成功后开始算的,不包含你的服务远程发送到 redis + redis 接收执行 的时延。
    0 0
  • 7911364440
    2022年9月7日 03:58
    两次相邻的任务间隔算了下都是大于超时时间的,感觉跟定时任务应该没关系
    0 0
  • vzhzhq
    2022年9月7日 03:58
    数据过期不等于没有数据,redis 的淘汰策略可以了解一下
    0 0
  • redorblacck886
    2022年9月7日 03:58
    过期时间这个有点不可靠 。 办法一:监听 redis key 过期的事件 可以达到你的目的。但是会消耗一定的 cpu 办法二:监听 binlog 来实现 。只要有更新你就刷进 redis 。完全不管有没有超时。 办法三:类似心跳方案、一个定时任务 每隔几秒就去刷数据 setNx 也可以
    0 0
  • RedBeanIce
    2022年9月7日 05:28
    建议不要问 ab 问题,因为 a 产生 b ,问 b
    0 0
  • IvanLi127
    2022年9月7日 05:28
    有数据的时候你把 ttl 查出来打印下看看呀?还要你要解决啥问题?我感觉 redis 过期时间不精确也很合理呀
    0 0
  • seth19960929
    2022年9月7日 05:28
    Redis 设置了过期时间, 肯定就是那个时间点过期. 楼上说的有问题 过期了 != 删除. redis 判断一个 key 不存在有两种, 一种是 key 不存在, 另一种是存在, 但是过期了没来得及删除 楼主这个不就是最简单的单任务锁吗, 如果服务器延迟大的话 尝试使用 EXPIREAT 设置过期时间, 而不是 EXPIRE
    0 0
  • edward1987
    2022年9月7日 06:30
    换个实现方式+1 总感觉你在走弯路...不如说下需求
    0 0
  • mitu9527
    2022年9月7日 06:30
    要么是个高级问题,要么是个低级问题,目前看不出来是哪种。
    0 0
  • Jooooooooo
    2022年9月7日 07:01
    是想用 redis 去做到毫秒级别的过期控制? 你得换个实现方案. 或者你的需求本身有问题.
    0 0
  • micean
    2022年9月7日 07:01
    很多信息没有给,50ms 的要求也很高,时间间隔最好以任务的预估完成时间估算。 比如第一次连接到 redis 的时间消耗的比较长(连接池经常这样),那么第二次扫描 redis 自然有可能还没过期的。 如果是用 redis 做分布式单任务,给你一个简单的方案 1. 用 xxx+时间戳作为键名 2. 时间戳为固定值,比如你的 50ms 的间隔,那么时间戳是 00:00:00.050 、00:00:00.100 、00:00:00.150 等等。如果是 00:00:00.067 运行的任务,那么去除余数是 00:00:00.050 。 3. 用 setnx 就能完成检查+过期 4. 任务计时器的线程不要承担业务代码
    0 0
  • fkdtz
    2022年9月7日 07:01
    Redis 过期策略确实是惰性删除的,但那也不意味着本该删掉的 key 还能 get 出来,如果是这样那过期有个毛用了。 感觉是你的业务逻辑写的有问题,get key 、set key 、set job start time 这三步哪里有问题,导致出现了时间差。 不行贴代码吧。
    0 0
  • tutu2000
    2022年9月7日 07:27
    ”判断 redis 中是否存在数据“跟过期 key 是否被删除没关系,只要过期了的 key ,redis 肯定返回不存在 看你设置的过期时间很短,很可能第二次任务写入时慢了,之后的任务又快了,导致差了几毫秒 key 还没过期。建议设置绝对过期时间试下,expireat
    0 0
  • baoyinlei
    2022年9月7日 07:57
    定时任务开启到 redis server 端真正执行命令也是需要时间的。
    0 0
  • xuanbg
    2022年9月7日 07:57
    才 50ms 就扫一次的任务最好放内存别放 redis 。读取 redis 数据怎么也要几个毫秒,影响太大了。
    0 0
  • buster
    2022年9月7日 07:57
    开始执行定时任务:00:00:00 checkExists request:00:00:01 NO and set Interval = 1min:00:00:02 ------------------------------------------- 下一个循环开始:00:01:00 checkExists request:00:01:01 此时那个 key 的 ttl 还剩余 1 到 2 秒,exist !
    0 0
  • Chinsung
    2022年9月7日 09:28
    你这个到 ms 级,本来就不准 你定时任务触发的时间戳,我们假设你是 xxl-job 或者 quartz 这种,xxl-job 触发的时间戳是 0,50ms,100ms 但是你定时任务触发时到你服务器的网络延迟,或者哪怕你是单机定时任务的线程切换延迟,再到你执行到 redis set 的延迟,再到 redis 请求的网络延迟,都可能会导致问题。 比如你任务触发是时钟 0ms ,设置 redis 实际是 1ms 了,那你 redis 过期时间到 51ms ,显然就有问题了
    0 0
  • urnoob
    2022年9月7日 09:28
    50ms 确实太短,局域网内可能都没那么快。 实现上给不要用 key 是否存在来做,放一对 kv ,判断的时候用 key 去取 v ,应该能避免你这种情况
    0 0