一、背景

对于一个部署在多台机器上的应用,程序运行时,如何保证多个机器上的定时任务只有一个机器上的任务被执行?
思路:对于每一个定时任务job都有一个唯一id,当发现改job处于运行状态时,其他机器都不会去调度这个job

二、解决方法

quartz的分布式解决方案
quartz介绍
Quartz是一个开源的作业调度包,能够运行在几乎任何java项目中,小到单机应用,大到电商系统。Quartz能够创建很容易的调度,也可以创建十个、百个、千个、甚至万个任务的复杂调度。Quartz将任务定义成java组件,能够执行几乎任何你定义的事情。Quartz也支持许多企业级特性,比如JTA和集群。Quartz的核心是Scheduler、Job、Trigger。Job负责定义需要执行的任务,Trigger负责调度策略,Scheduler负责将二者组合。

quartz的分布式解决方案
启用quartz的分布式任务调度处理,只需如下两个步骤,程序无需修改

在数据库中创建quartz需要的表。这些表由quartz自己维护,用于保存数据和维护程序运行状态,这些表对于程序员而言是透明的,不需要关注,只需创建好表即可。
在工程的src下增加quartz.properties配置文件,进行集群相关操作的配置。

三、具体实现

1、创建quartz需要的数据库表
下载地址:链接:https://pan.baidu.com/s/1ndA-PbkcLG8bUivV-rBnMw
提取码:aux1
位置:quartz-2.2.1\docs\dbTable,找到自己数据库所需的表。我使用的是达梦数据库,使用的tables_oracle.sql建表。
2、创建quartz.properties放在代码的sources下
#==============================================================

#Configure Main Scheduler Properties
#==============================================================
org.quartz.scheduler.instanceName = quartzScheduler
org.quartz.scheduler.instanceId = AUTO

#==============================================================
#Configure JobStore
#==============================================================
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 20000
org.quartz.jobStore.dataSource = myDS

#==============================================================
#Configure DataSource
#==============================================================
org.quartz.dataSource.myDS.driver = dm.jdbc.driver.DmDriver
org.quartz.dataSource.myDS.URL = jdbc\:dm\://IP \:port  
org.quartz.dataSource.myDS.user = username
org.quartz.dataSource.myDS.password = password
org.quartz.dataSource.myDS.maxConnections = 30
#==============================================================
#Configure ThreadPool
#==============================================================
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

3、修改applicationContext.xml,其中jobFactory这个属性在我博客已经讲解,为了Job类可以使用@Autowired注解

https://blog.csdn.net/qq_21190847/article/details/105799721

 <bean id="scheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
          <!--为了可以使用@Autowired注解-->
        <property name="jobFactory" ref="jobFactory"></property>
         <!--获取集群配置类,连接数据库-->
        <property name="applicationContextSchedulerContextKey" value="applicationContext" />
        <property name="configLocation" value="classpath:quartz.properties" />
    </bean>

4、测试,具体创建定时任务管理:包括任务的crud, 任务的暂停、恢复在我博客中已说明。

https://blog.csdn.net/qq_21190847/article/details/105364762

启动两个tomcat设置同一个job和同一个执行时间。发现只有一个会被执行。

@PersistJobDataAfterExecution
@DisallowConcurrentExecution// 不允许并发执行
public class QuartzJobExample implements Job {
    @Override
    public void execute(JobExecutionContext arg0) throws JobExecutionException {
        JobDataMap map=arg0.getJobDetail().getJobDataMap();
        String version = String.valueOf(map.get("jobName"));
        System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "★★★★★★★★★★★");
        System.out.println("★★★★★★★★★★★"+version);
    }
}
Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐