zoukankan      html  css  js  c++  java
  • quartz集群分布式(并发)部署解决方案

    项目中使用分布式并发部署定时任务,多台跨JVM,按照常理逻辑每个JVM的定时任务会各自运行,这样就会存在问题,多台分布式JVM机器的应用服务同时干活,一个是加重服务负担,另外一个是存在严重的逻辑问题,比如需要回滚的数据,就回滚了多次,刚好quartz提供很好的解决方案。

    集群分布式并发环境中使用QUARTZ定时任务调度,会在各个节点会上报任务,存到数据库中,执行时会从数据库中取出触发器来执行,如果触发器的名称和执行时间相同,则只有一个节点去执行此任务。

    如果此节点执行失败,则此任务则会被分派到另一节点执行,中途也会自动检查失效的定时调度,发现不成功的,其他节点立马接过来继续完成定时任务。对应的定时任务调度表比较多,有11个。

    此方法是结合Spring与quartz,实际解决方案如下:

    ####applicationContext-scheduler.xml###  spring 3.11

    <?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:context="http://www.springframework.org/schema/context"
      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.2.xsd
                http://www.springframework.org/schema/context
                http://www.springframework.org/schema/context/spring-context-3.2.xsd
                http://www.springframework.org/schema/task
                http://www.springframework.org/schema/task/spring-task-3.2.xsd">
    
      <context:annotation-config />
      <context:component-scan base-package="com.dennis.walking.api.web.schedule" />
    
    
      <bean id="rollbackOrderStatus" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
        <property name="jobClass" value="com.dennis.walking.api.web.schedule.ReleaseQtyAndUpdateOrderStatusSchedule" />
        <property name="durability" value="true" />
      </bean>
      <bean id="rollbackOrderStatusTrigger" class="com.dennis.walking.api.web.schedule.PersistableCronTriggerFactoryBean">
        <property name="jobDetail" ref="rollbackOrderStatus" />
        <property name="cronExpression">
          <value>0 0/5 * * * ?</value>
        </property>
        <property name="timeZone">
          <value>GMT+8:00</value>
        </property>
      </bean>
      
     	
      <bean id="quartzScheduler" parent="baseQuartzScheduler">
        <property name="configLocation" value="classpath:quartz.properties" />
        <property name="autoStartup" value="true" />
        <!-- This name is persisted as SCHED_NAME in db. for local testing could change to unique name to avoid collision with dev server -->
        <property name="schedulerName" value="apiQuartzScheduler" />
        <!-- NOTE: Must add both the jobDetail and trigger to the scheduler! -->
        <property name="triggers">
          <list>
            <ref bean="rollbackOrderStatusTrigger" /> 
          </list>
        </property>
    
        <property name="jobDetails">
          <list>
            <ref bean="rollbackOrderStatus" />
          </list>
        </property>
      </bean>
    
      <bean id="baseQuartzScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
        <!-- 
        <property name="configLocation" value="classpath:quartz.properties" />
         -->
        <property name="dataSource" ref="dataSource" />
        <property name="transactionManager" ref="transManager" />
    
        <!-- This name is persisted as SCHED_NAME in db. for local testing could change to unique name to avoid collision with dev server -->
        <property name="schedulerName" value="quartzScheduler" />
    
        <!-- Will update database cron triggers to what is in this jobs file on each deploy. Replaces all previous trigger and job data that was in the database. YMMV -->
        <property name="overwriteExistingJobs" value="true" />
        <!-- 
        <property name="autoStartup" value="true" />
         -->
        <property name="applicationContextSchedulerContextKey" value="applicationContext" />
        <property name="jobFactory">
          <bean class="com.dennis.walking.api.web.schedule.AutowiringSpringBeanJobFactory" />
        </property>
        <!-- NOTE: Must add both the jobDetail and trigger to the scheduler! -->
        <!-- 
        <property name="jobDetails">
          <list>
          </list>
        </property>
        <property name="triggers">
          <list>
          </list>
        </property>
        -->
      </bean>
    </beans>

    记得对应下面的三个类文件。

    ###quartz.properties###

    # Using Spring datasource in quartzJobsConfig.xml
    # Spring uses LocalDataSourceJobStore extension of JobStoreCMT
    org.quartz.jobStore.useProperties=true
    org.quartz.jobStore.tablePrefix=QRTZ_
    org.quartz.jobStore.isClustered=true
    # 10 mins
    org.quartz.jobStore.clusterCheckinInterval=600000
    org.quartz.scheduler.skipUpdateCheck=true
    
    # Change this to match your DB vendor
    org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
    # Needed to manage cluster instances
    org.quartz.scheduler.instanceId=AUTO
    org.quartz.scheduler.instanceName=MY_JOB_SCHEDULER
     
    org.quartz.scheduler.rmi.export=false
    org.quartz.scheduler.rmi.proxy=false
    org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
    org.quartz.threadPool.threadCount=10
    org.quartz.threadPool.threadPriority=5
    org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread=true
    
    # Configure Plugins
    org.quartz.plugin.triggHistory.class = 
      org.quartz.plugins.history.LoggingTriggerHistoryPlugin
    org.quartz.plugin.triggHistory.triggerFiredMessage = 
      Trigger {1}.{0} fired job {6}.{5} at: {4, date, HH:mm:ss MM/dd/yyyy}
    org.quartz.plugin.triggHistory.triggerCompleteMessage = 
      Trigger {1}.{0} completed firing job {6}.{5} at {4, date, HH:mm:ss MM/dd/yyyy}.

    quartz定时调度常用时间点设置

    "0 0 12 * * ?"                     Fire at 12pm (noon) every day
    "0 15 10 ? * *"                   Fire at 10:15am every day
    "0 15 10 * * ?"                   Fire at 10:15am every day
    "0 15 10 * * ? *"                 Fire at 10:15am every day
    "0 15 10 * * ? 2005"           Fire at 10:15am every day during the year 2005
    "0 * 14 * * ?"                     Fire every minute starting at 2pm and ending at 2:59pm, every day
    "0 0/5 14 * * ?"                  Fire every 5 minutes starting at 2pm and ending at 2:55pm, every day
    "0 0/5 14,18 * * ?"              Fire every 5 minutes starting at 2pm and ending at 2:55pm, AND fire every 5 minutes starting at 6pm and ending at 6:55pm, every day
    "0 0-5 14 * * ?"                   Fire every minute starting at 2pm and ending at 2:05pm, every day
    "0 10,44 14 ? 3 WED"         Fire at 2:10pm and at 2:44pm every Wednesday in the month of March.
    "0 15 10 ? * MON-FRI"        Fire at 10:15am every Monday, Tuesday, Wednesday, Thursday and Friday
    "0 15 10 15 * ?"                  Fire at 10:15am on the 15th day of every month
    "0 15 10 L * ?"                    Fire at 10:15am on the last day of every month
    "0 15 10 ? * 6L"                   Fire at 10:15am on the last Friday of every month
    "0 15 10 ? * 6L"                   Fire at 10:15am on the last Friday of every month
    "0 15 10 ? * 6L 2002-2005"   Fire at 10:15am on every last Friday of every month during the years 2002, 2003, 2004 and 2005
    "0 15 10 ? * 6#3"                 Fire at 10:15am on the third Friday of every month

    真实运行的业务类:ReleaseQtyAndUpdateOrderStatusSchedule.java

    应为要持久化等特性操作,需要继承 QuartzJobBean

    由于要被持久化,所以不能存放xxxxManager类似对象,

    只能从每次从QuartzJobBean注入的ApplicationContext 中去取出

    继承QuartzJobBean,实现方法executeInternal

    package com.dennis.walking.api.web.schedule;
    
    import org.apache.commons.logging.Log;
    import org.apache.commons.logging.LogFactory;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.scheduling.quartz.QuartzJobBean;
    import org.springframework.stereotype.Component;
    import com.dennis.walking.api.service.OrderService;
    
    
    @Component
    public class ReleaseQtyAndUpdateOrderStatusSchedule extends QuartzJobBean {
      
      private Log log = LogFactory.getLog(this.getClass());
      
      @Autowired
      OrderService orderService;
      
          
      protected void executeInternal(JobExecutionContext arg0)
          throws JobExecutionException {
        log.info("dennis test execute schedule start ");
        try {
          orderService.releaseQtyAndUpdateOrderStatus();
        } catch (Exception e) {
          e.printStackTrace();
          log.error("execute ReleaseQtyAndUpdateOrderStatus schedule error:"
              + e.getMessage());
        }
        log.info("dennis test exxcute schedule end");
      }
    }

    持久化数据:PersistableCronTriggerFactoryBean.java  保存数据到数据库中

    package com.dennis.walking.api.web.schedule;
    
    import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
    import org.springframework.scheduling.quartz.JobDetailAwareTrigger;
    
    /**
     * Needed to set Quartz useProperties=true when using Spring classes, because
     * Spring sets an object reference on JobDataMap that is not a String
     * 
     * @see http://site.trimplement.com/using-spring-and-quartz-with-jobstore-properties
     *      /
     * @see http
     *      ://forum.springsource.org/showthread.php?130984-Quartz-error-IOException
     */
    public class PersistableCronTriggerFactoryBean extends CronTriggerFactoryBean {
      @Override
      public void afterPropertiesSet() {
        super.afterPropertiesSet();
        System.out.println("PersistableCronTriggerFactoryBean-------------------");
        // Remove the JobDetail element
        getJobDataMap().remove(JobDetailAwareTrigger.JOB_DETAIL_KEY);
      }
    }

    ###AutowiringSpringBeanJobFactory.java### 使用spring的 bean文件时,需要使用此类

    package com.dennis.walking.api.web.schedule;
    
    import org.quartz.spi.TriggerFiredBundle;
    import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.scheduling.quartz.SpringBeanJobFactory;
    
    /**
     * Autowire Quartz Jobs with Spring context dependencies
     * 
     * @see http
     *      ://stackoverflow.com/questions/6990767/inject-bean-reference-into-a-quartz
     *      -job-in-spring/15211030#15211030
     */
    public final class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory
        implements ApplicationContextAware {
    
      private transient AutowireCapableBeanFactory beanFactory;
    
      public void setApplicationContext(final ApplicationContext context) {
        beanFactory = context.getAutowireCapableBeanFactory();
      }
    
      @Override
      protected Object createJobInstance(final TriggerFiredBundle bundle)
          throws Exception {
        final Object job = super.createJobInstance(bundle);
        beanFactory.autowireBean(job);
        System.out.println("AutowiringSpringBeanJobFactory-------------------");
        return job;
      }
    }

    ###tables_mysql.sql###  需要建立的11张表

    #
    # Quartz seems to work best with the driver mysql-connector-java-5.1.34-bin.jar
    # 
    # PLEASE consider using mysql with innodb tables to avoid locking issues
    #
    # In your Quartz properties file, you'll need to set 
    # org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
    #
    
    DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS;
    DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS;
    DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE;
    DROP TABLE IF EXISTS QRTZ_LOCKS;
    DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS;
    DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS;
    DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS;
    DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS;
    DROP TABLE IF EXISTS QRTZ_TRIGGERS;
    DROP TABLE IF EXISTS QRTZ_JOB_DETAILS;
    DROP TABLE IF EXISTS QRTZ_CALENDARS;
    
    
    CREATE TABLE QRTZ_JOB_DETAILS
      (
        SCHED_NAME VARCHAR(120) NOT NULL,
        JOB_NAME  VARCHAR(200) NOT NULL,
        JOB_GROUP VARCHAR(200) NOT NULL,
        DESCRIPTION VARCHAR(250) NULL,
        JOB_CLASS_NAME   VARCHAR(250) NOT NULL,
        IS_DURABLE VARCHAR(1) NOT NULL,
        IS_NONCONCURRENT VARCHAR(1) NOT NULL,
        IS_UPDATE_DATA VARCHAR(1) NOT NULL,
        REQUESTS_RECOVERY VARCHAR(1) NOT NULL,
        JOB_DATA BLOB NULL,
        PRIMARY KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
    );
    
    CREATE TABLE QRTZ_TRIGGERS
      (
        SCHED_NAME VARCHAR(120) NOT NULL,
        TRIGGER_NAME VARCHAR(200) NOT NULL,
        TRIGGER_GROUP VARCHAR(200) NOT NULL,
        JOB_NAME  VARCHAR(200) NOT NULL,
        JOB_GROUP VARCHAR(200) NOT NULL,
        DESCRIPTION VARCHAR(250) NULL,
        NEXT_FIRE_TIME BIGINT(13) NULL,
        PREV_FIRE_TIME BIGINT(13) NULL,
        PRIORITY INTEGER NULL,
        TRIGGER_STATE VARCHAR(16) NOT NULL,
        TRIGGER_TYPE VARCHAR(8) NOT NULL,
        START_TIME BIGINT(13) NOT NULL,
        END_TIME BIGINT(13) NULL,
        CALENDAR_NAME VARCHAR(200) NULL,
        MISFIRE_INSTR SMALLINT(2) NULL,
        JOB_DATA BLOB NULL,
        PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
        FOREIGN KEY (SCHED_NAME,JOB_NAME,JOB_GROUP)
            REFERENCES QRTZ_JOB_DETAILS(SCHED_NAME,JOB_NAME,JOB_GROUP)
    );
    
    CREATE TABLE QRTZ_SIMPLE_TRIGGERS
      (
        SCHED_NAME VARCHAR(120) NOT NULL,
        TRIGGER_NAME VARCHAR(200) NOT NULL,
        TRIGGER_GROUP VARCHAR(200) NOT NULL,
        REPEAT_COUNT BIGINT(7) NOT NULL,
        REPEAT_INTERVAL BIGINT(12) NOT NULL,
        TIMES_TRIGGERED BIGINT(10) NOT NULL,
        PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
        FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
            REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
    );
    
    CREATE TABLE QRTZ_CRON_TRIGGERS
      (
        SCHED_NAME VARCHAR(120) NOT NULL,
        TRIGGER_NAME VARCHAR(200) NOT NULL,
        TRIGGER_GROUP VARCHAR(200) NOT NULL,
        CRON_EXPRESSION VARCHAR(200) NOT NULL,
        TIME_ZONE_ID VARCHAR(80),
        PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
        FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
            REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
    );
    
    CREATE TABLE QRTZ_SIMPROP_TRIGGERS
      (          
        SCHED_NAME VARCHAR(120) NOT NULL,
        TRIGGER_NAME VARCHAR(200) NOT NULL,
        TRIGGER_GROUP VARCHAR(200) NOT NULL,
        STR_PROP_1 VARCHAR(512) NULL,
        STR_PROP_2 VARCHAR(512) NULL,
        STR_PROP_3 VARCHAR(512) NULL,
        INT_PROP_1 INT NULL,
        INT_PROP_2 INT NULL,
        LONG_PROP_1 BIGINT NULL,
        LONG_PROP_2 BIGINT NULL,
        DEC_PROP_1 NUMERIC(13,4) NULL,
        DEC_PROP_2 NUMERIC(13,4) NULL,
        BOOL_PROP_1 VARCHAR(1) NULL,
        BOOL_PROP_2 VARCHAR(1) NULL,
        PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
        FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP) 
        REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
    );
    
    CREATE TABLE QRTZ_BLOB_TRIGGERS
      (
        SCHED_NAME VARCHAR(120) NOT NULL,
        TRIGGER_NAME VARCHAR(200) NOT NULL,
        TRIGGER_GROUP VARCHAR(200) NOT NULL,
        BLOB_DATA BLOB NULL,
        PRIMARY KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP),
        FOREIGN KEY (SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
            REFERENCES QRTZ_TRIGGERS(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP)
    );
    
    CREATE TABLE QRTZ_CALENDARS
      (
        SCHED_NAME VARCHAR(120) NOT NULL,
        CALENDAR_NAME  VARCHAR(200) NOT NULL,
        CALENDAR BLOB NOT NULL,
        PRIMARY KEY (SCHED_NAME,CALENDAR_NAME)
    );
    
    CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS
      (
        SCHED_NAME VARCHAR(120) NOT NULL,
        TRIGGER_GROUP  VARCHAR(200) NOT NULL, 
        PRIMARY KEY (SCHED_NAME,TRIGGER_GROUP)
    );
    
    CREATE TABLE QRTZ_FIRED_TRIGGERS
      (
        SCHED_NAME VARCHAR(120) NOT NULL,
        ENTRY_ID VARCHAR(95) NOT NULL,
        TRIGGER_NAME VARCHAR(200) NOT NULL,
        TRIGGER_GROUP VARCHAR(200) NOT NULL,
        INSTANCE_NAME VARCHAR(200) NOT NULL,
        FIRED_TIME BIGINT(13) NOT NULL,
        SCHED_TIME BIGINT(13) NOT NULL,
        PRIORITY INTEGER NOT NULL,
        STATE VARCHAR(16) NOT NULL,
        JOB_NAME VARCHAR(200) NULL,
        JOB_GROUP VARCHAR(200) NULL,
        IS_NONCONCURRENT VARCHAR(1) NULL,
        REQUESTS_RECOVERY VARCHAR(1) NULL,
        PRIMARY KEY (SCHED_NAME,ENTRY_ID)
    );
    
    CREATE TABLE QRTZ_SCHEDULER_STATE
      (
        SCHED_NAME VARCHAR(120) NOT NULL,
        INSTANCE_NAME VARCHAR(200) NOT NULL,
        LAST_CHECKIN_TIME BIGINT(13) NOT NULL,
        CHECKIN_INTERVAL BIGINT(13) NOT NULL,
        PRIMARY KEY (SCHED_NAME,INSTANCE_NAME)
    );
    
    CREATE TABLE QRTZ_LOCKS
      (
        SCHED_NAME VARCHAR(120) NOT NULL,
        LOCK_NAME  VARCHAR(40) NOT NULL, 
        PRIMARY KEY (SCHED_NAME,LOCK_NAME)
    );
    
    
    commit;
    
    ###如果定时任务比较多,建议增加索引提升速度。
    /*
    reate index idx_qrtz_j_req_recovery on qrtz_job_details(SCHED_NAME,REQUESTS_RECOVERY);  
    create index idx_qrtz_j_grp on qrtz_job_details(SCHED_NAME,JOB_GROUP);  
    create index idx_qrtz_t_j on qrtz_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);  
    create index idx_qrtz_t_jg on qrtz_triggers(SCHED_NAME,JOB_GROUP);  
    create index idx_qrtz_t_c on qrtz_triggers(SCHED_NAME,CALENDAR_NAME);  
    create index idx_qrtz_t_g on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP);  
    create index idx_qrtz_t_state on qrtz_triggers(SCHED_NAME,TRIGGER_STATE);  
    create index idx_qrtz_t_n_state on qrtz_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP,TRIGGER_STATE);  
    create index idx_qrtz_t_n_g_state on qrtz_triggers(SCHED_NAME,TRIGGER_GROUP,TRIGGER_STATE);  
    create index idx_qrtz_t_next_fire_time on qrtz_triggers(SCHED_NAME,NEXT_FIRE_TIME);  
    create index idx_qrtz_t_nft_st on qrtz_triggers(SCHED_NAME,TRIGGER_STATE,NEXT_FIRE_TIME);  
    create index idx_qrtz_t_nft_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME);  
    create index idx_qrtz_t_nft_st_misfire on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_STATE);  
    create index idx_qrtz_t_nft_st_misfire_grp on qrtz_triggers(SCHED_NAME,MISFIRE_INSTR,NEXT_FIRE_TIME,TRIGGER_GROUP,TRIGGER_STATE);  
    create index idx_qrtz_ft_trig_inst_name on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME);  
    create index idx_qrtz_ft_inst_job_req_rcvry on qrtz_fired_triggers(SCHED_NAME,INSTANCE_NAME,REQUESTS_RECOVERY);  
    create index idx_qrtz_ft_j_g on qrtz_fired_triggers(SCHED_NAME,JOB_NAME,JOB_GROUP);  
    create index idx_qrtz_ft_jg on qrtz_fired_triggers(SCHED_NAME,JOB_GROUP);  
    create index idx_qrtz_ft_t_g on qrtz_fired_triggers(SCHED_NAME,TRIGGER_NAME,TRIGGER_GROUP);  
    create index idx_qrtz_ft_tg on qrtz_fired_triggers(SCHED_NAME,TRIGGER_GROUP);  
    */

    本文测试软件环境使用的jar版本是:

    quartz-2.2.1.jar mysql-connector-java-5.1.34.jar

    linux apache-tomcat-7.0.47 ava version "1.7.0_72" 64位

    windows7  java version "1.7.0_45"  64位 jetty

    Quartz是一个开放源码项目,专注于任务调度器,提供了极为广泛的特性如持久化任务,集群和分布式任务等。 Quartz核心是调度器,还采用多线程管理。

    1.持久化任务:当应用程序停止运行时,所有调度信息不被丢失,当你重新启动时,调度信息还存在,这就是持久化任务(保存到数据库表中)。

    2.集群和分布式处理:当在集群环境下,当有配置Quartz的多个客户端时(节点),采用Quartz的集群和分布式处理时,我们要了解几点好处

    1) 一个节点无法完成的任务,会被集群中拥有相同的任务的节点取代执行。

    2) Quartz调度是通过触发器的类别来识别不同的任务,在不同的节点定义相同的触发器的类别,这样在集群下能稳定的运行,一个节点无法完成的任务,会被集群中拥有相同的任务的节点取代执行。

    3)分布式体现在当相同的任务定时在一个时间点,在那个时间点,不会被两个节点同时执行。

    Quartz的 Task(11 张表)实例化采用数据库存储,基于数据库引擎及 High-Available 的策略(集群的一种策略)自动协调每个节点的 Quartz。

  • 相关阅读:
    最长有效括号
    C++ 环形缓存区的实现
    vector的原理与底层实现
    聚合分析与分组
    求两个数的最大公约数
    单例模式
    工厂方法模式
    责任链模式
    适配器模式
    策略模式
  • 原文地址:https://www.cnblogs.com/adolfmc/p/9012825.html
Copyright © 2011-2022 走看看