如何实现一个任务调度系统,看这篇文章就够了

本文探讨了如何实现任务调度系统,从Quartz框架开始,介绍了分布式锁模式和ElasticJob-Lite的优势与挑战,进一步讨论了中心化流派的MQ模式和XXL-JOB的特点。文章还分享了自研任务调度系统的经验,强调了技术选型的重要性,并提出了幂等性和任务监控的注意事项。
摘要由CSDN通过智能技术生成

阅读一篇「定时任务框架选型」的文章时,一位网友的留言到了我:

我看过那么多所谓的教程,大部分都是教“如何使用工具”的,没有多少是教“如何制作工具”的,能教“如何仿制工具”的都已经是凤毛麟角,中国 软件行业,缺的是真正可以“制作工具”的程序员,而绝对不缺那些“使用工具”的程序员! ...... ”这个业界最不需要的就是“会使用XX工具的工程师”,而是“有创造力的软件工程师”!业界所有的饭碗,本质就是“有创造力的软件工程师”提供出来的啊!

写这篇文章,想和大家从头到脚说说任务调度,希望大家读完之后,能够理解实现一个任务调度系统的核心逻辑。

1 Quartz

Quartz是一款Java开源任务调度框架,也是很多Java工程师接触任务调度的起点。

下图显示了任务调度的整体流程:

Quartz的核心是三个组件。

  • 任务:Job 用于表示被调度的任务;
  • 触发器:Trigger 定义调度时间的元素,即按照什么时间规则去执行任务。一个Job可以被多个Trigger关联,但是一个Trigger 只能关联一个Job;
  • 调度器 :工厂类创建Scheduler,根据触发器定义的时间规则调度任务。

 

上图代码中Quartz 的JobStore是 RAMJobStore,Trigger 和 Job 存储在内存中。

执行任务调度的核心类是 QuartzSchedulerThread 。

  1. 调度线程从JobStore中获取需要执行的的触发器列表,并修改触发器的状态;
  2. Fire触发器,修改触发器信息(下次执行触发器的时间,以及触发器状态),并存储起来。
  3. 最后创建具体的执行任务对象,通过worker线程池执行任务。

接下来再聊聊 Quartz 的集群部署方案。

Quartz的集群部署方案,需要针对不同的数据库类型(MySQL , ORACLE) 在数据库实例上创建Quartz表,JobStore是: JobStoreSupport 。

这种方案是分布式的,没有负责集中管理的节点,而是利用数据库行级锁的方式来实现集群环境下的并发控制。

scheduler实例在集群模式下首先获取{0}LOCKS表中的行锁,Mysql 获取行锁的语句:

{0}会替换为配置文件默认配置的QRTZ_。sched_name为应用集群的实例名,lock_name就是行级锁名。Quartz主要有两个行级锁触发器访问锁 (TRIGGER_ACCESS) 和 状态访问锁(STATE_ACCESS)。 

这个架构解决了任务的分布式调度问题,同一个任务只能有一个节点运行,其他节点将不执行任务,当碰到大量短任务时,各个节点频繁的竞争数据库锁,节点越多性能就会越差。

2 分布式锁模式

Quartz的集群模式可以水平扩展,也可以分布式调度,但需要业务方在数据库中添加对应的表,有一定的强侵入性。

有不少研发同学为了避免这种侵入性,也探索出分布式锁模式

业务场景:电商项目,用户下单后一段时间没有付款,系统就会在超时后关闭该订单。

通常我们会做一个定时任务每两分钟来检查前半小时的订单,将没有付款的订单列表查询出来,然后对订单中的商品进行库存的恢复,然后将该订单设置为无效。

我们使用Spring Schedule的方式做一个定时任务。

@Scheduled(cron = "0 */2 * * 
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值