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

    • 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 的跳过机制——从声明式 skip().skipLimit() 到自定义 SkipPolicy,掌握跳过的最佳实践。

定义与作用

跳过(Skip)是 Spring Batch 在遇到预期的、可恢复的数据异常时的处理策略。当一条数据在 Read/Process/Write 阶段失败时,框架可以选择跳过该条数据,继续处理后续数据。

飞翔科技运营部高英提供的 CSV 中偶尔有格式错误的行,小崔用 skip 策略优雅处理:

"CSV 中 5000 条数据有 20 条格式有问题——跳过它们继续处理剩下的 4980 条,总好过因为 20 条错误让整个 Job 失败。"

核心原理

Skip 的内部机制

当启用容错模式后,一个 Chunk 中某条 Item 发生 skip 异常时:

  1. 框架回滚整个 Chunk 事务
  2. 以 Chunk Size=1 重新扫描该 Chunk 的所有 Item
  3. 定位到失败的那一条,跳过它
  4. 将其他正常的 Item 正常处理并通过 Writer 写出

完整示例

场景一:声明式 Skip 配置

@Bean
public Step skipCapableStep(JobRepository jobRepository,
                              PlatformTransactionManager tx,
                              ItemReader<Order> reader,
                              ItemProcessor<Order, Order> processor,
                              ItemWriter<Order> writer) {
    return new StepBuilder("skipCapableStep", jobRepository)
            .<Order, Order>chunk(100, tx)
            .reader(reader)
            .processor(processor)
            .writer(writer)
            .faultTolerant()
            .skip(FlatFileParseException.class)      // CSV 解析错误
            .skip(ValidationException.class)          // 业务校验失败
            .skip(DataIntegrityViolationException.class) // 数据库约束冲突
            .skipLimit(100)                           // 最多跳 100 条
            .skipPolicy(new LimitCheckingSkipPolicy(100)) // 等价于上一行
            .build();
}

场景二:自定义 SkipPolicy

public class ConditionalSkipPolicy implements SkipPolicy {

    @Override
    public boolean shouldSkip(Throwable t, long skipCount) 
            throws SkipLimitExceededException {
        // 只跳过特定消息的异常
        if (t instanceof ValidationException ve 
                && ve.getMessage().contains("DUPLICATE")) {
            return true; // 重复数据 → 跳过
        }
        if (t instanceof FlatFileParseException) {
            return skipCount < 50; // CSV 错误最多跳 50 条
        }
        return false; // 其他异常不跳过
    }
}

操作前后对比:

无跳过策略:
  Chunk 100 条,第 63 条 CSV 格式错误
  → 整个 Chunk ROLLBACK → Step FAILED → Job FAILED
  结果: 5000 条数据全部未处理

有跳过策略(skipLimit=100):
  Chunk 100 条,第 63 条 CSV 格式错误
  → 跳过第 63 条,第 1-62, 64-100 条正常写入 → COMMIT
  → 后续 Chunk 继续
  结果: 4980 条成功,20 条跳过,Job COMPLETED

易错场景与避坑

反例一:skip 太宽泛——使用 Exception.class

// ❌ 捕获所有异常 → 包括 NPE、OOM 等严重错误!
.faultTolerant()
.skip(Exception.class)  // ❌ 太宽泛:连 NullPointerException 都跳过
.skipLimit(100)

正确做法:只跳过预期的、可恢复的异常类型(FlatFileParseException、ValidationException、DataIntegrityViolationException)。

反例二:skipLimit 设置过大

// ❌ skipLimit=10000 但总数据只有 5000 条 → 所有数据都可能被跳过
.skipLimit(10000)

正确做法:skipLimit 应该是一个有意义的阈值。超过这个阈值说明数据质量问题严重,应该让 Job 失败以便人工介入。

面试高频考点

Q1:skip 时框架如何处理已成功的 Item?

框架回滚整个 Chunk,然后以 Chunk Size=1 重新扫描该 Chunk 的每一条 Item。正常 Item 重新处理并写回,失败的那一条被跳过。这保证了:①跳过的只有失败项;②事务一致性;③WriteCount 不包含跳过的项。

Q2:skip 和 retry 的执行顺序?

先 Retry 后 Skip。框架先检查异常是否匹配 retry(),如果匹配且未达 retryLimit 则重试。重试耗尽后仍失败,再检查是否匹配 skip()。如果匹配且未达 skipLimit 则跳过。


上一章:重启与重试下一章:作业流与条件决策

上一页
重启与重试