分布式定时任务

本文介绍了定时任务的概念,包括Linux的crontab、JDK的Timer、ScheduledExecutor和Spring Scheduler等。随着业务发展,单机定时任务暴露出单点风险和资源分布不均等问题。文章探讨了分布式定时任务的两种处理方式——抢占式和协同式,并提到了Quartz、TBSchedule和Elastic-Job等开源框架作为解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

什么是定时任务

       定时任务是指基于给定的时间点、给定的时间间隔或者给定的执行次数自动执行一项或多项任务。

常用的定时任务如下。
1.crontab命令
直接使用linux系统自带的crontab程序进行定时任务控制。

2.JDK Timer
java.util.Timer定时器为单线程,定时调度所拥有的TimeTask任务。

public class HelloTimerTask extends TimerTask{
	@Override
	public void run() {
		System.out.println(new Date());
	}
}
public class HelloTimer {
	public static void main(String[] args) {
		Timer timer = new Timer();
		System.out.println(new Date());
		timer.schedule(new HelloTimerTask(), 1000, 2000);
	}
}

Timer类缺陷如下:

  • 时间延迟不准确。由于是单线程执行,如果某个任务执行时间过长,可能导致后续任务时间延迟。
  • 异常终止。如果任务抛出未捕获的异常,会导致Timer线程终止,所有任务终止。
  • 执行周期任务时依赖系统时间。当系统时间发生变化,会导致执行上的变化。

3.ScheduledExecutor

public class HelloTask implements Runnable{
	@Override
	public void run() {
		System.out.println(new Date());
	}
}
public class HelloScheduledExecutor {
	public static void main(String[] args) {
		ScheduledExecutorService executor = Executors.newScheduledThreadPool(3);
		executor.schedule(new HelloTask(),1,TimeUnit.SECONDS);
		executor.scheduleAtFixedRate(new HelloTask(), 1, 2, TimeUnit.SECONDS);
		executor.scheduleWithFixedDelay(new HelloTask(), 1, 2, TimeUnit.SECONDS);
	}
}

ScheduledThreadPool内部使用线程池实现,各个任务之间并发执行,互相隔离

4.Spring Scheduler

public class HelloTask {
	public void doTask() {
		SimpleDateFormat sdf = new SimpleDateFormat("YYYY/MM/dd HH:mm:ss.SSS");
		System.out.println("hello world " + sdf.format(new Date()));
		try {
			Thread.sleep(5000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
	   http://www.springframework.org/schema/task
       http://www.springframework.org/schema/task/spring-task-3.1.xsd">
	<bean id="helloTask" class="com.test.SpringScheduler.HelloTask"></bean>
	<task:scheduler id="myScheduler" pool-size="3" />
	<task:scheduled-tasks scheduler="myScheduler">
		<task:scheduled ref="helloTask" method="doTask" cron="*/3 * * * * ?" />
	</task:scheduled-tasks>
</beans>
ApplicationContext context = new ClassPathXmlApplicationContext("spring-context.xml");

5.Quartz

传统定时任务存在的问题

       业务发展初期,批量任务可以部署在单一服务器上,上文的定时任务实现方式均可以实现,但是随着业务增多,全部作业调度任务放在一台机器上执行存在明显缺陷:单点风险和资源分布不均。

如何将任务分散到不同机器上执行
1.通过配置参数分散运行,例如在不同机器的properties文件中配置不同的任务;
2.通过分布式锁互斥执行,详见https://blog.youkuaiyun.com/penguinhao/article/details/83515024

分布式定时任务的两种处理方式

  • 抢占式:谁先获得资源谁执行,这种模式无法将单个任务的数据交给其他节点协同处理,一般用于处理数据量较小、任务较多的场景。
  • 协同式:可以将单个任务处理的数据均分到多个JVM中处理,提高数据的并行处理能力。

开源框架

Quartz的分布式模式
TBSchedule
Elastic-Job

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值