首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

简易的、可靠的分布式定时任务设计方案

前言

在许多业务场景中,需要定时处理一些业务任务,比如菠菜现在负责的智能调度系统,需要定时的执行调度任务来给运力进行推单。那业内也有很多解决方案比如AMQ的延时队列等,今天菠菜来聊一种简易的、可靠的、同时性能也很高的设计方案。

总体思路

废话不多说,先上图:

总体的设计思路是本地建立Timer + 远程备份的方式。比如上图,服务器1建立本地Timer,并将定时任务所需要的数据+触发时间点存储到一个中间存储用于备份。正常情况下本地触发Timer并执行定时任务,执行完后删除远程备份。对于异常情况下(如某一台服务宕机了),每台服务器会额外建立一个定时任务,这个定时任务会定时检测远程备份中是否有需要恢复的定时任务,若有则获取相关数据并进行执行。

具体如何实现

本文以Golang + Redis为例,具体描述一下该如何落地。

建立并备份定时任务

对于某一个分布式调度任务,需要提前设定好TimerCallback(即回调方法),Redis链接实例(即文中的RecoverRedis),以及远程备份的存储的key(即文中的RecoverID)。

那我们再来看看建立定时任务需要的参数:

data,回调方法时,需要传入的数据

delaySeconds,延时时间点,即n秒后执行该任务

recoverSeconds,任务执行n秒后还未完成就算任务失败,并且需要进行恢复。

这里需要详细说一下recoverSeconds的作用,它会作为判断任务是否正常被执行的重要依据。若一个定时任务为5秒后执行(delaySeconds),并且最大执行时间为10秒(recoverSeconds)。15秒后,若其他服务器发现该任务还在备份列表中,则认为原有任务执行失败,需要进行恢复。

还如上图,若执行完定时调度,则会将备份进行删除。

异常情况恢复定时任务

每台机器都会建立一个Ticker,每隔一段时间去Redis中查询超时的任务,若发现有超时的任务,则进行争抢,若争抢成功则进行恢复。

由于备份任务的时候采用的是Redis的zset(如zadd key timeoutTime data)。那获取超时的任务就比较简单了,使用zrangebyscore key 0 now即可将超时的任务获取到。至于争抢的过程,需要利用分布式锁,这里就不多介绍了,之前的文章里有提到。争抢到后,调用之前设置的TimerCallback方法并将data传入进行调度任务的恢复。

至此,简易的分布式调度设计思路阐述完成。其实在实际业务场景中还可以对该设计进行微调,比如在调度任务执行过程中不断给备份内容进行续命,而不是写死一个recoverSeconds等。

最后

好久不写公众账号了,趁着年前略轻松,抽时间写篇文章,也以这种方式给大家拜个早年!祝大家新年快乐!

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20190131G0UCMW00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券