如何避免扫描数据库且保证低延迟触发定时任务的一些思考

本文介绍如何利用Redis的ZSet数据结构实现高效灵活的定时任务管理。包括用户自定义触发时间的任务处理、固定时间循环任务的执行及系统层面的定时任务错峰处理策略。

用户自定义触发时间

用户自定义触发时间,存在不固定,所以需要秒级的扫描来触发任务。但是如果直接扫表的话,会给数据库造成比较大的压力。可以考虑基于RedisZSet来处理

  1. 明确年月日时分秒, 即希望在一个具体的时间执行,这种执行基本就是一次性。
    解决方案:

    1. 把时间转换为时间戳, 然后使用zset的数据格式,key根据业务决定,将同一类的定时统一划分到一个key
    2. value按需决定是否需要放入定时任务所需要的数据, score即为用户设置的定时任务触发时间的时间戳。
    3. 定时任务扫描, 调用redis操作类的opsForZSet().rangeByScore(key, 0, 当前时间戳)方法,这样即会把缓存中score小于当前时间的数据扫描出来,而这部分数据则是满足定时任务的数据。然后将这部分数据取出来直接执行业务即可。
    4. 执行完业务之后, 调用opsForZSet().removeRangeByScore(key, 0, 当前时间戳)清除这段时间的数据,避免下次再次扫描到。
    5. 可以看到第3步扫描到的数据大小依赖于定时的执行间隔, 如果实时性要求比较高,可以将定时设置为每秒执行也是可以的。注意这里面的一些时间定义一定要是在开始就定义的变量,后续保证使用的时间都不能变化。如上面3和4的当前时间戳。
  2. 只明确时分(秒), 即时间是固定的,但对年月日没要求, 这种执行基本就是循环的,每天或者都会执行
    解决方案

    1. 将时间部分的数据转换为毫秒值, 如10:30, 则对应的毫秒值为10 * 60 * 60 * 1000 + 30 * 60 * 1000,然后使用zset的数据格式,key根据业务决定,将同一类的定时统一划分到一个key
    2. value按需决定是否需要放入定时任务所需要的数据, sc
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值