Quartz定时任务

一、Quartz 介绍

官网:http://www.quartz-scheduler.org/

Quartz是一个定时调度的框架,指定时间内触发执行某个动作;它完全由 Java 写成,并设计用于 J2SE 和 J2EE 应用中。

为什么要用定时任务

  • 无需手动触发 :无需页面(人工)触发动作
  • 执行时间准确:会在准确的时间内进行业务处理
  • 低耦合:单独为一个动作体,可以自行开关,不影响其他业务功能

在这里插入图片描述

  • Scheduler(调度器)

    • Scheduler 是 Quartz 的核心组件,它负责管理和调度所有的任务。Scheduler 可以启动、停止、暂停和恢复任务的执行,还可以配置任务的触发条件和执行计划。
  • Job(任务)

    • Job 是需要被调度执行的实际任务。您可以定义自己的 Job 类,实现自己的业务逻辑,并将其注册到 Scheduler 中。Quartz 提供了不同类型的 Job,如无状态的 Job、有状态的 Job 等,以满足不同的需求。
  • Trigger(触发器)

    • Trigger 负责定义任务的触发条件,即何时触发任务的执行。您可以为每个 Job 关联一个或多个 Trigger,根据时间表达式(如 Cron 表达式)或者特定的时间间隔来配置触发器。
  • JobDetail(任务详情)

    • JobDetail 是与 Job 相关联的详细信息,包括 Job 的名称、所属的 Job 类、Job 的身份标识等。每个 Job 都有一个对应的 JobDetail。
  • JobStore(任务存储)

    • JobStore 是 Quartz 的持久化机制,负责将任务和调度相关的信息存储到数据库或其他存储介质中。这样即使应用程序重启或者服务器关闭,已经配置的调度任务仍然可以得到保留。
  • Listener(监听器)

    • Quartz 提供了丰富的监听器接口,让您可以监控任务的状态变化、执行情况以及异常事件。通过实现 Quartz 的监听器接口,您可以在任务执行前后、暂停和恢复、出现错误等情况下执行额外的逻辑。
  • ThreadPool(线程池)

    • Scheduler 使用线程池来并发执行任务,提高任务的处理效率。Quartz 允许您配置线程池的大小、类型和特性,以适应不同的负载情况。

三大核心组件

  • 任务Job:即想要调用的任务类,需要实现org.quartz.job接口,并重写execute()方法,任务调度时会执行execute()方法。(最新版本实现QuartzJobBean类,重写executeInternal方法)
  • 触发器Trigger:即执行任务的触发器,当满足什么条件时会去执行你的任务Job,主要分为根据时长间隔执行的SimpleTrigger和根据日历执行的CronTrigger。
  • 调度器Scheduler:即将Trigger和Job绑定之后,根据Trigger中的设定,负责进行Job调度的组件。

二、项目配置

定时任务用于用户在小程序下单后未支付,订单处于"待支付"状态,如果在规定时间内(5分钟)未支付,则自动取消订单

导入依赖

<dependency>
    <groupId>org.quartz-scheduler</groupId>
    <artifactId>quartz</artifactId>
    <exclusions>
        <exclusion>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
        </exclusion>
    </exclusions>
</dependency>

在数据库中添加任务配置

INSERT INTO sys_job (
    job_name, 
    job_group, 
    invoke_target, 
    cron_expression, 
    status, 
    remark
) VALUES (
    '订单超时自动取消',
    'DEFAULT',
    'orderTimeoutTask.cancelTimeoutOrders',
    '0 */1 * * * ?',  -- 每1分钟执行一次
    '0',  -- 启用状态
    '自动取消超时未支付订单'
);

创建定时任务执行类

@Component("orderTimeoutTask")
public class OrderTimeoutTask
{
    private static final Logger logger = LoggerFactory.getLogger(OrderTimeoutTask.class);

    @Autowired
    private RemoteOrderService remoteOrderService;

    /**
     * 执行订单超时自动取消任务
     *
     * @param params 参数
     * @throws TaskException 异常
     */
    public void cancelTimeoutOrders(String params) throws TaskException
    {
        logger.info("开始执行订单超时自动取消任务,参数:{}", params);

        try {
            // 调用远程服务取消超时订单
            int canceledCount = remoteOrderService.cancelTimeoutOrders();
            logger.info("订单超时自动取消任务执行完成,共取消 {} 个订单", canceledCount);
        } catch (Exception e) {
            logger.error("订单超时自动取消任务执行失败", e);
            throw new TaskException("订单超时自动取消任务执行失败: " + e.getMessage(), TaskException.Code.TASK_EXISTS);
        }
    }
}

订单服务实现

@Override
public int cancelTimeoutOrders() {
    // 计算超时时间点(5分钟前)
    LocalDateTime timeoutTime = LocalDateTime.now().minusMinutes(5);
    
    // 查询超时未支付的订单
    LambdaQueryWrapper<OrderMain> wrapper = new LambdaQueryWrapper<>();
    wrapper.eq(OrderMain::getOrderStatus, 0) // 待支付状态
           .lt(OrderMain::getCreateTime, timeoutTime);
    
    List<OrderMain> timeoutOrders = orderMainMapper.selectList(wrapper);
    
    int cancelledCount = 0;
    for (OrderMain order : timeoutOrders) {
        // 更新订单状态为已取消
        order.setOrderStatus(3); // 3表示已取消
        order.setUpdateTime(LocalDateTime.now());
        orderMainMapper.updateById(order);
        
        releaseInventory(order);
        
        cancelledCount++;
    }
    
    log.info("自动取消了 {} 个超时未支付订单", cancelledCount);
    return cancelledCount;
}

RemoteOrderService调用订单服务

@FeignClient(value = "manage-customer")
public interface RemoteOrderService {

    /**
     * 取消超时未支付的订单
     *
     * @return 取消的订单数量
     */
    @PostMapping("/app/order/cancelTimeoutOrders")
    int cancelTimeoutOrders();
}

实现

在这里插入图片描述

三、简单定时任务

@Scheduled是Spring框架内置的定时任务注解,不用引入额外依赖,只需在启动类加@EnableScheduling,再给方法加@Scheduled注解就能用。它支持Cron表达式、固定延迟(fixedDelay)、固定频率(fixedRate)等多种调度方式,适合简单的单机定时任务,比如单机环境下的日志清理、数据统计。

优势:轻量无侵入,和Spring生态无缝集成,代码简洁,不用额外部署中间件,适合快速实现简单定时需求。

缺点:不支持集群,集群部署时每个节点都会执行任务,会导致重复执行;没有可视化管理界面,任务配置、监控、日志查看都依赖代码和系统日志;动态修改任务规则需要重启服务,灵活性差,也没有故障转移能力,节点挂了任务就中断。

每隔5分钟自动从配置服务中拉取最新的主键映射配置,并更新到本地缓存

	/**
     * 定时刷新配置
     */
    @Scheduled(cron = "0 0/5 * * * ?")
    public void refreshPrimaryKeyMap() {
        try {
            Map<String, String> newConfig = primaryKeyConfigService.loadLatestPrimaryKeyMap();
            if (!newConfig.isEmpty()) {
                TABLE_PRIMARY_KEY_MAP = new HashMap<>(newConfig);
                log.info("🔄 配置刷新完成,共{}张表", newConfig.size());
            }
        } catch (Exception e) {
            log.error("❌ 配置刷新异常", e);
        }
    }

每30分钟自动检测系统是否处于异常状态,若满足特定条件,则静默执行一次 Canal 连接的重置与清理操作,以实现“自愈”或“容错恢复”。

   @Scheduled(cron = "0 */30 * * * ?")
    public void scheduledReset() {
        try {
            if (consecutiveAckErrors.get() > 2 || needFullReset.get() || totalAckErrors.get() > 5) {
                log.info("🔄 定时任务检测到需要重置,执行静默清理...");
                needFullReset.set(true);

                // 静默执行清理(不抛异常)
                try {
                    safeDisconnect();
                    safeSleep(1000);
                    canalConnector.connect();
                    canalConnector.subscribe(".*\\..*");
                    canalConnector.rollback();
                    resetAckState();
                    log.debug("✅ 定时清理完成");
                } catch (Exception e) {
                    log.debug("定时清理异常: {}", e.getMessage());
                }
            }
        } catch (Exception e) {
            log.error("定时重置任务异常", e);
        }
    }

四、主流定时任务框架对比表

特性 Quartz Elastic-Job-Cloud / Lite XXL-JOB Antares OpenCron @Scheduled (Spring)
依赖 MySQL(集群模式需 DB) JDK 1.7+,ZooKeeper(Lite 版),Mesos(Cloud 版) MySQL + JDK 1.7+ JDK 1.7+,Redis + ZooKeeper JDK 1.7+,Tomcat 8+ 无额外依赖(Spring 环境即可)
高可用(HA) 支持(基于 DB 锁,多节点竞争) 强支持(ZK 注册中心,自动故障转移) 支持(调度中心集群 + 执行器注册) 支持(ZK 实现服务发现) 不支持(单点) 不支持(仅单机)
Cron 表达式支持 ✅(原生支持) ✅(支持 Quartz 和 crontab) ✅(标准 Spring cron)
文档完善度 ✅ 非常完善 ✅ 官方文档较全(但 Cloud 版已停止维护) ✅ 中文文档极佳 ⚠️ 文档较少 ⚠️ 文档一般 ✅ Spring 官方文档完善
学习/使用难度 ⭐ 简单(单机) ⭐⭐⭐(集群需理解 DB 锁机制) ⭐⭐⭐⭐(需掌握 ZK/Mesos,架构复杂) ⭐⭐(开箱即用,部署简单) ⭐⭐⭐ ⭐⭐ ⭐(最简单)
高级功能 - 持久化 - 事务支持 - 分片 - 失效转移 - 弹性扩容 - 作业监控 - 幂等 - GLUE(在线编码) - 日志查看 - 报警 - 任务依赖 - 分片 - 失效转移 - 弹性扩容 - 在线执行 - Kill 任务 - 状态查询 - 轻量 - 与 Spring 深度集成
是否开源 ✅ Apache 2.0 ✅ Apache 2.0(ElasticJob 已捐给 Apache,更名为 ShardingSphere-ElasticJob) ✅ MIT License ✅(GitHub 开源) ✅(GitHub 开源) ✅(Spring Framework)
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐