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

    • 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章 运维与监控

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

重启与重试

本章定位:区分并掌握 Spring Batch 的两个核心容错能力——Job 重启(Restart)和 Step 重试(Retry),理解它们的触发条件、限制和协作方式。

定义与作用

概念粒度触发条件行为
Job 重启Job 级别上次 JobExecution 状态为 FAILED从失败的 Step 重新启动
Step 重试Item 级别当前 Item 处理抛出可重试异常重新执行该 Item 的 Processor/Writer

飞翔科技架构师白歌的区别:

"重启是整条流水线停电后重新合闸——从上次断掉的工位继续。重试是一个零件加工失败后再试一次——机器还在转,只是这个零件返工。"

核心原理

重启流程

重试流程

关键区分

维度重启重试
触发方式手动重新 jobLauncher.run()框架自动
异常要求JobExecution FAILED异常类型匹配 retry()
状态依赖依赖 ExecutionContext不依赖持久化状态
适用异常数据库连接断开、内存溢出瞬时故障(锁超时、网络抖动)
不适用异常—逻辑错误(NPE、数据校验失败)

完整示例

场景一:断点续传——文件处理中途崩溃后重启

@Bean
public Step restartableFileStep(JobRepository jobRepository,
                                  PlatformTransactionManager tx) {
    return new StepBuilder("restartableFileStep", jobRepository)
            .<String, String>chunk(50, tx)
            .reader(new ResumableFileReader("data.txt")) // 实现 ItemStream
            .writer(items -> {
                for (String item : items) {
                    if (item.contains("BOOM")) {
                        throw new RuntimeException("Simulated crash at: " + item);
                    }
                    System.out.println("Processed: " + item);
                }
            })
            .build();
}

运行过程:

第 1 次执行:
  Chunk 1: 50 条 → COMMIT → ExecutionContext 记录行号 50
  Chunk 2: 50 条 → COMMIT → ExecutionContext 记录行号 100
  Chunk 3: 读到含 "BOOM" 的行 → write() 抛异常 → ROLLBACK
  JobExecution: FAILED

第 2 次执行(相同参数):
  从 ExecutionContext 恢复: current.line = 100
  Chunk 3: 从第 101 行开始读 50 条 → 再次遇到 "BOOM" → FAILED

修复 BOOM 后第 3 次执行:
  从 ExecutionContext 恢复: current.line = 100
  Chunk 3: 50 条正常 → COMMIT
  ... 后续全部正常 → Job COMPLETED

场景二:重试配置——数据库死锁自动恢复

@Bean
public Step retryCapableStep(JobRepository jobRepository,
                               PlatformTransactionManager tx,
                               ItemReader<Order> reader,
                               ItemWriter<Order> writer) {
    return new StepBuilder("retryCapableStep", jobRepository)
            .<Order, Order>chunk(100, tx)
            .reader(reader)
            .writer(writer)
            .faultTolerant()
            .retry(DeadlockLoserDataAccessException.class)  // 数据库死锁 → 重试
            .retryLimit(3)                                   // 最多 3 次
            .skip(DataIntegrityViolationException.class)     // 约束冲突 → 跳过
            .skipLimit(50)
            .build();
}

操作前后对比:

场景无容错有 retry + skip
瞬时死锁(第 50 条)Step FAILED,147 条白读最多重试 3 次后恢复
约束冲突(第 200 条)Step FAILED,200 条白读跳过该条,继续处理
连续死锁(5 条)Step FAILED前 3 条重试 3 次,后 2 条超出 → FAILED

易错场景与避坑

反例一:preventRestart() 阻止重启

// ❌ 设置禁止重启 → Job 失败后无法恢复
return new JobBuilder("job", jobRepository)
        .preventRestart()
        .start(step)
        .build();
// 失败后用相同参数再启动 → JobRestartException

反例二:retry 不加 retryLimit

// ❌ 只声明 retry 异常类型但不设上限 → 无限重试
.faultTolerant()
.retry(TransientException.class)
// 忘记 .retryLimit() → 默认 0 → 等效于不重试

面试高频考点

Q1:重启和重试的协作——重试耗尽后如何进入重启?

重试在 Item 级别,重启在 Job 级别。如果一条 Item 重试 3 次都失败且不匹配 skip,Step 失败 → Job 失败。此时可以修复数据后重启 Job——重启时框架跳过已成功 COMMIT 的 Chunk,从失败的 Chunk 重新开始。

Q2:哪些异常适合重试,哪些不适合?

适合重试:瞬时故障(死锁、网络超时、连接池耗尽)。不适合重试:数据错误(NullPointerException、格式错误、校验失败)——重试也不会改变结果。对于数据错误应使用 skip 而非 retry。


上一章:监听器详解下一章:跳过策略

下一页
跳过策略