分布式延时任务解决方案

场景

        之前在业务中遇到一个需求:老师发布一个作业,然后设置了一个提醒时间。到了提醒时间,需要给每个学生发送一条IM提醒消息。这是一个典型的延时任务的场景。下面我们就来讨论一下,对于延时任务的实现方案。


延时方案

1、MQ方案:RabbitMQ的死信队列、以及RocketMQ本身都是可以通过延时消费,来达到延时任务调度的目的。这种方案依赖MQ中间件的队列,是严格按照在队列中的顺序来消费消息,即使后面的任务过期时间到了,也需要等到压在前面的任务消费完才能消费。这个方案比较适合那种固定过期时间的任务,比如订单30分钟未付款关单,都是从丢到MQ中那一刻开始过30分钟,这种就不存在后面消息过期了,前面的消息时间还未到的情况;

2、Redis方案:通过给key设置过期时间,然后监听到过期之后,对业务进行处理。这种方案的调度时间不是很准确;还可以通过队列的形式,不停去遍历,找到时间到了的任务,拿出来执行。这种调度时间会存在误差;

3、时间轮的方案:时间轮的数据结构是数组+双向链表,在逻辑上是一个环;可以指定这个环的刻度,旋转一圈的时间。调度时间可以精确到秒。netty和dubbo中都有现成的实现例子。这种方案可以调度随意时间的任务。它每走一个刻度,就遍历每个刻度中的链表,找出到了执行时间的任务进行调度。这个方案唯一不好的地方:它是基于内存的,一旦重启,时间轮中的数据就没了。所以,如果遇到这种重启的情况,就需要重建时间轮中的任务,这就需要对任务是否已调度在业务中进行标记,然后保存到物理表中。

        文章开头描述的这个场景,我就是通过时间轮的方案实现的。这种延迟任务的场景,在业务开发中很普遍,每次都得把相同的方案重复实现一遍。之前也没有想着说怎么实现一个公共的组件。最近想着能否实现一个公共的组件,全公司直接调用就行了。刚开始的时候,我先网上找了一下,看有没有现成的方案。后来看了xxl-mq的源码,它这个里面有专门实现延迟消息的方案,但是它的调度,比较粗粒度。我测试了一下,延迟大概3秒左右。对于延迟要求不是很高的场景,是个很好的选择。本想着改一下xxl-mq的源码,让它的调度时间精确一点。后来感觉,如果仅仅为了使用一下延迟功能,就重新部署一个中间件,感觉不划算。正好我们公司使用xxl-job做的定时任务的调度,所以,我就想着,是否能给xxl-job增加延迟任务调度的能力。

        通读xxl-job的源码,发现完全可以借助它调度的机制、心跳的机制,这些都不需要我重新实现,我只需要实现延迟任务调度的逻辑即可。而且对业务没有任何侵入性,完美。花了一天时间,把延时任务的功能写完了,测试了一下,对于并发比较小的情况,都是及时调度,如果并发很大的情况,延时在一秒以内。源码上传到了Gitee上,有兴趣的可以看看。也欢迎大家多多交流指正:xxl-job-plus: 通过改造xxl-job,实现分布式延迟任务的功能。调度时间精确,误差不超过1秒。

        具体使用方法:

        1、使用@XxlDelay注解标记处理延迟任务的业务逻辑方法;

        2、使用XxlJobDelayHelper#pushDelayTask静态方法发布延迟任务;

        3、使用XxlJobDelayHelper#cancel静态方法取消延迟任务;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值