乐途乐途
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
主页
  • 计算机基础

    • TCP/IP
    • Linux
    • HTTP
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C
    • C++
    • Java SE
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • Maven 入门
    • Maven 进阶
    • MyBatis
    • Spring
    • Spring MVC
  • Java

    • Spring Boot
    • Spring Cloud
    • Spring Cloud Alibaba
    • Spring Security
    • Spring AI
    • Spring Batch
    • Kafka
    • Java 设计模式
  • 缓存

    • Redis
  • 搜索引擎

    • Elasticsearch
  • 分布式协调

    • ZooKeeper
联系
阿里云
  • 学习路径
  • 第1章 批处理概述与 Spring Batch 核心理念

    • Spring Batch 概述
    • Job-Instance-Execution 三层生命周期
    • 三层架构
    • Chunk 处理模型
    • Tasklet 处理模型
  • 第2章 Job与作业配置

    • Job 详解
    • Job 配置
    • JobLauncher 详解
    • JobParameters 详解
    • JobRepository 详解
  • 第3章 Step与执行模型

    • Step 详解
    • Step 配置
    • ExecutionContext 详解
    • ItemStream 与状态管理
    • StepScope 与 JobScope
  • 第4章 ItemReader数据读取

    • ItemReader 详解
    • FlatFileItemReader 详解
    • JdbcItemReader 详解
    • MultiResourceItemReader 详解
  • 第5章 ItemProcessor 数据处理

    • ItemProcessor 详解
  • 第6章 ItemWriter 数据写出

    • ItemWriter 详解
    • FlatFileItemWriter 详解
    • CompositeItemWriter 详解
    • JdbcBatchItemWriter 详解
  • 第7章 Chunk 处理与事务边界

    • Chunk 处理模型详解
    • 事务边界
  • 第8章 作业参数与启动

    • 命令行与 Web 启动
  • 第9章 监听器与拦截器

    • 监听器详解
  • 第10章 重启重试与跳过策略

    • 重启与重试
    • 跳过策略
  • 第11章 作业流与条件决策

    • 作业流与条件决策
  • 第12章 分区与并行处理

    • 分区详解
    • 并行 Step 与 Split
  • 第13章 与 Spring Boot 集成实践

    • Spring Boot 集成
  • 第15章 运维与监控

    • 大作业设计模式
    • 运维与监控

Job-Instance-Execution 三层生命周期

本章定位:彻底理解 Spring Batch 中最核心的三层生命周期模型——Job、JobInstance 和 JobExecution 的关系,这是掌握重启机制和状态管理的基础。

定义与作用

Spring Batch 将一次批处理任务的生命周期划分为三个层次:

概念含义类比
Job作业的静态定义,由 Step 组成,是编写的蓝图一份菜谱——定义了做什么、怎么做
JobInstanceJob + JobParameters 确定的逻辑运行实例按菜谱做一顿饭——同样的菜谱 + 相同的食材 = 同一顿饭
JobExecutionJobInstance 的物理执行尝试这顿饭的第一遍炒菜(可能糊了,需要重新炒)

飞翔科技后端开发小崔有一次面试被问到这三者的区别时,用了一个生动的比喻:

"Job 是代码里写的那个处理逻辑;JobInstance 是'用今天的文件跑这个逻辑'这个实例;JobExecution 是这次跑的过程记录——如果中途数据库挂了,修复后重新跑,就是同一个 JobInstance 的第二个 JobExecution。"

核心原理

生命周期流转

关键规则

规则说明
Job + JobParameters = JobInstance 的唯一标识同一 Job + 同一组 JobParameters → 同一个 JobInstance
同一 JobInstance 可以有多于一个 JobExecution首次执行失败后,用相同参数重启会产生新的 JobExecution
已完成的 JobInstance 不能再次启动状态为 COMPLETED 的 JobInstance 再次启动会抛出 JobInstanceAlreadyCompleteException
失败的 JobInstance 可以重启状态为 FAILED 的 JobInstance 可以创建新的 JobExecution

状态流转详细

完整示例

场景一:飞翔科技——学生数据导入的失败与重启

背景:小崔开发的学生数据导入 Job 在第一次运行时,由于数据库连接超时在 Step 2 失败。他用相同的 JobParameters 重启后,Spring Batch 从 Step 2 开始恢复,跳过了已完成的 Step 1。

第一次执行——失败:

Job: [studentImportJob] with params: {input.file=students_20260613.csv, run.id=1}
  JobInstance Id: 1
  JobExecution Id: 1
  Step 1 [validateStep]: COMPLETED (1000 records validated)
  Step 2 [processStep]: FAILED (Connection timeout at record 542)
  Step 3 [reportStep]: NOT STARTED

对应元数据表:

BATCH_JOB_INSTANCE:
  JOB_INSTANCE_ID=1, JOB_NAME='studentImportJob', JOB_KEY='abc123'

BATCH_JOB_EXECUTION:
  JOB_EXECUTION_ID=1, JOB_INSTANCE_ID=1, STATUS='FAILED'

BATCH_STEP_EXECUTION:
  STEP_EXECUTION_ID=1, JOB_EXECUTION_ID=1, STEP_NAME='validateStep', STATUS='COMPLETED'
  STEP_EXECUTION_ID=2, JOB_EXECUTION_ID=1, STEP_NAME='processStep', STATUS='FAILED'

第二次执行——重启成功:

Job: [studentImportJob] with params: {input.file=students_20260613.csv, run.id=1}
  JobInstance Id: 1  ← 同一个 JobInstance!
  JobExecution Id: 2  ← 新的 JobExecution
  Step 1 [validateStep]: SKIPPED (already COMPLETED in previous execution)
  Step 2 [processStep]: STARTED from record 542 (recovered from ExecutionContext)
  Step 2 [processStep]: COMPLETED (458 records processed)
  Step 3 [reportStep]: COMPLETED

关键行为:

  1. 使用相同的 JobParameters → 同一个 JobInstance,产生新的 JobExecution
  2. Step 1 因为已 COMPLETED → 自动跳过
  3. Step 2 从 ExecutionContext 中恢复进度 → 从第 542 条继续
  4. 使用 RunIdIncrementer 时 run.id 自动递增,保证每次运行产生不同 JobInstance

场景二:电商订单处理——防止重复执行

背景:产品经理孔蓝担心同一份订单文件被重复处理导致重复发货。运营杨英需要用 Spring Batch 的 JobInstance 唯一性机制防止这种情况。

@Bean
public Job orderProcessJob(JobRepository jobRepository,
                            Step orderStep) {
    return new JobBuilder("orderProcessJob", jobRepository)
            .incrementer(new RunIdIncrementer()) // 每次启动 run.id 自增
            .start(orderStep)
            .build();
}

用不同日期参数启动——不同的 JobInstance:

// 6 月 13 日的订单
JobParameters params1 = new JobParametersBuilder()
        .addString("orderDate", "2026-06-13")
        .addLong("run.id", 1L)
        .toJobParameters();
jobLauncher.run(orderProcessJob, params1); // → JobInstance #1

// 6 月 14 日的订单——不同参数,不同 JobInstance
JobParameters params2 = new JobParametersBuilder()
        .addString("orderDate", "2026-06-14")
        .addLong("run.id", 2L)
        .toJobParameters();
jobLauncher.run(orderProcessJob, params2); // → JobInstance #2(新实例)

// 重复执行 6 月 13 日——相同参数,冲突!
JobParameters params3 = new JobParametersBuilder()
        .addString("orderDate", "2026-06-13")
        .addLong("run.id", 3L) // run.id 不同!
        .toJobParameters();
jobLauncher.run(orderProcessJob, params3); // → JobInstance #3(run.id 让参数不同了!)

运行结果:

调用daterun.id结果原因
第 1 次2026-06-131新 JobInstance #1,正常执行新参数组合
第 2 次2026-06-142新 JobInstance #2,正常执行新参数组合
第 3 次2026-06-133新 JobInstance #3run.id 不同 → 不同参数 → 新实例

这就是 RunIdIncrementer 的作用——通过自动递增 run.id,让每次执行产生不同的 JobParameters,从而创建新的 JobInstance。如果没有它,用相同的业务参数第二次启动会失败。

易错场景与避坑

反例一:不理解 JobInstance 唯一性导致"无法重启"

小崔在某次测试中,一个 Job 跑完后想重新跑一次验证,直接用相同的命令行参数:

java -jar batch-app.jar --spring.batch.job.name=studentImportJob input.file=students.csv

结果报错:

JobInstanceAlreadyCompleteException:
A job instance already exists and is complete for parameters={input.file=students.csv}.
If you want to run this job again, change the parameters.

原因:相同的 Job + 相同的 JobParameters 只能对应一个已完成的 JobInstance。

解决方案:

// 方案一:使用 RunIdIncrementer(推荐)
@Bean
public Job job(JobRepository jobRepository, Step step) {
    return new JobBuilder("studentImportJob", jobRepository)
            .incrementer(new RunIdIncrementer()) // 每次 run.id 自动 +1
            .start(step)
            .build();
}

// 方案二:添加时间戳参数
JobParameters params = new JobParametersBuilder()
        .addString("input.file", "students.csv")
        .addLong("time", System.currentTimeMillis()) // 每次不同
        .toJobParameters();

反例二:误以为 JobInstance = 一次 App 启动

新来的前端开发黄俪在学 Spring Batch 时以为"每次启动 Spring Boot 应用就是一次 JobInstance":

// ❌ 错误理解:每次启动应用 = 新 JobInstance
// 实际上同一个 App 启动后可以执行多个 Job 和 JobInstance
@SpringBootApplication
public class BatchApp {
    public static void main(String[] args) {
        SpringApplication.run(BatchApp.class, args);
        // Job 自动执行一次 → 这只是 1 个 JobExecution
    }
}

正确理解:JobInstance 由 Job + JobParameters 决定,与应用进程无关。同一个 App 进程中可以:

// 一个 App 进程内执行多个 JobInstance
jobLauncher.run(job1, params1); // → JobInstance #1
jobLauncher.run(job1, params2); // → JobInstance #2(参数不同)
jobLauncher.run(job2, params3); // → 另一个 Job 的 JobInstance

面试高频考点

Q1:Job、JobInstance、JobExecution 三者的关系?

Job 是静态定义(代码中的 Bean)。JobInstance 是 Job + JobParameters 确定的逻辑实例。JobExecution 是 JobInstance 的物理执行尝试。一个 JobInstance 可以有多个 JobExecution(失败重启),但一个已完成(COMPLETED)的 JobInstance 不能再次启动。

Q2:什么是 JobParameters?为什么它是 JobInstance 的唯一性标识?

JobParameters 是启动 Job 时传入的键值对参数集合(如日期、文件路径、run.id)。Spring Batch 根据 Job 名称 + JobParameters 的哈希值来判断是否同一个 JobInstance。这是实现"相同任务不重复执行"和"失败任务可重启"两个需求的基础。

Q3:如何在每天定时执行同一个 Job 而不冲突?

① 使用 RunIdIncrementer 让 run.id 每次递增;② 在 JobParameters 中加入日期参数(如 addString("date", LocalDate.now().toString()));③ 加入时间戳参数。三种方式都能保证每次产生新的 JobInstance。


上一章:三层架构下一章:Chunk 处理模型

上一页
Spring Batch 概述
下一页
三层架构