欢迎光临
我们一直在努力

Spring Batch 高级特性与实践详解

Spring Batch高级特性与实践详解

定位:Batch 第 02 篇,讲透重启续跑机制、跳过与重试策略、并行处理模式、监听器与生产工程实践 适用版本:Spring Batch 5.x(Spring Boot 3.x)


目录

  • 一、重启与续跑
  • 二、跳过与重试
  • 三、并行处理
  • 四、监听器与可观测
  • 五、工程实践
  • 六、总结
  • 七、常见高频面试题

一、重启与续跑

1.1 机制

执行失败 → 元数据记录了执行到哪个 Step、哪个 Chunk
重启(用同一 JobInstance)→ 从失败的 Step 继续
已成功的 Chunk 不重复(已提交),从失败位置往后跑

1.2 条件与限制

要点说明
Step 可重启 需要记录位置(Reader 可定位,如数据库按 id 继续)
已完成 Step 不重跑 默认跳过已 COMPLETED 的 Step
强制重跑 allowStartIfComplete(true) 可让已完成 Step 重新执行
不可恢复的场景 流式读无位置记录、副作用已外部发生——重跑会重复

1.3 重启的前提是幂等

重启意味着部分数据会被重新处理——写操作必须幂等(唯一键去重/状态机),否则重跑产生重复数据。这是批处理设计的第一原则。


二、跳过与重试

2.1 Skip(跳过)

指定某类异常时跳过该条,继续处理后续数据(限制跳过总数):
.faultTolerant()
.skip(ValidationException.class)
.skipLimit(100)

用途:脏数据/校验不通过的条目不阻塞整个批处理;超过 skipLimit 才失败。

2.2 Retry(重试)

指定某类异常时重试该条(限制次数):
.retry(DeadlockLoserDataAccessException.class)
.retryLimit(3)

用途:瞬态故障(死锁、网络抖动)自动重试。

2.3 记录与监听

SkipListener:onSkipInRead/onSkipInProcess/onSkipInWrite —— 记录被跳过的数据

纪律:跳过的数据必须可追溯(落日志/落表),否则"数据少了"无法排查。


三、并行处理

3.1 四种模式

模式做法注意
多线程 Step 单 Step 内多线程并行处理(.throttleLimit/线程池) Reader/Processor/Writer 必须线程安全
并行 Step 互不依赖的 Step 用 Flow 同时执行 步骤间无数据依赖
分区(Partitioning) 把大任务按范围拆成子分区,各分区独立并行 分区键要可拆分(如按 id 段)
远程分块 读在主节点,处理分发到多机 跨进程,架构更复杂

3.2 多线程的线程安全要求

并行处理时:
Reader 被多线程调用 → 必须支持并发读或加锁
Processor 无状态
Writer 批量写要支持并发提交
不满足 → 数据错乱/丢失

3.3 分区示例思想

数据范围 1~1000 万
→ 拆成 10 个分区(1~100万、100万~200万…)
→ 每分区一个独立的处理实例并行跑
→ 汇总等待全部分区完成

适合数据可按键自然切分、各分区无交互的场景。


四、监听器与可观测

4.1 监听器体系

监听器时机
JobExecutionListener Job 开始/结束
StepExecutionListener Step 开始/结束
ChunkListener 每个 Chunk 前后
ItemReadListener 等 单条读/处理/写前后与异常

4.2 用途

① 日志:记录执行开始/结束、耗时、读写计数
② 指标:对接监控(吞吐、失败率、时长)
③ 通知:成功/失败发告警
④ 资源准备/清理:开始前准备、结束后清理

执行元数据(读写计数、提交数、状态)本身已入库,是监控的数据源。


五、工程实践

5.1 幂等设计(最重要)

批处理必然重跑(失败重启/补数),写操作必须幂等:
① 唯一键:业务唯一索引,重复插入被拒
② 状态机:已处理状态不再重复处理
③ 去重表/去重键:处理前检查

5.2 调度与编排

生产用外部调度平台(而非应用内 @Scheduled):
依赖编排(A 完成后跑 B)、失败告警、手动重跑、执行日历

5.3 资源隔离

批处理对库的压力大:
① 错峰:避开在线高峰
② 限流:控制并发与批量大小,避免拖垮在线库
③ 读从库/独立库:大批量读走从库或专用库

5.4 元数据治理

执行历史持续增长 → 定期清理(保留期策略)
关键执行结果归档审计


六、总结

  • 重启续跑:基于元数据从失败位置继续;前提是 Reader 可定位 + 写操作幂等;已完成 Step 默认不重跑。
  • 容错:Skip 跳脏数据(限数量 + 必须记录)、Retry 抗瞬态故障(限次数)。
  • 并行:多线程 Step(线程安全要求)、并行 Step(Flow)、分区(按键拆分)、远程分块;按数据可拆分性选择。
  • 监听器:Job/Step/Chunk/Item 各级钩子,支撑日志、指标、告警;执行元数据是监控数据源。
  • 工程纪律:幂等第一、调度平台化、资源隔离防拖垮在线、元数据定期清理。

  • 七、常见高频面试题

    1. Spring Batch 如何实现失败后从断点续跑?

    要点:基于执行元数据。每个 Chunk 是提交点,执行状态(哪个 Step、哪个 Chunk、读到哪)持久化在元数据表;失败后用同一 JobInstance 重启,框架跳过已成功的部分,从失败的 Step/Chunk 继续。前提:① Step 可重启——Reader 能定位继续位置(如按主键范围);② 写操作幂等——重跑不产生重复。限制:已完成的 Step 默认不重跑(需 allowStartIfComplete 强制)。

    2. 为什么批处理必须做幂等?

    要点:重跑是批处理的常态——失败重启、人工补数、重复触发都可能让部分数据被再次处理。若写操作不幂等,重跑产生重复数据(重复结算、重复发通知,资损风险)。实现:① 业务唯一键(唯一索引拒绝重复插入);② 状态机(已处理状态跳过);③ 去重表/幂等键检查。幂等是批处理可靠性的第一设计原则,与在线接口的幂等要求同源。

    3. Skip 和 Retry 策略怎么用?要注意什么?

    要点:Skip——指定某类异常(如校验失败)跳过该条继续处理,配 skipLimit 限制跳过总数,超限才失败;用于脏数据不阻塞批处理。Retry——指定瞬态异常(死锁、网络抖动)重试该条,配 retryLimit;用于抗瞬时故障。注意:① 被跳过的数据必须记录(SkipListener 落日志/表),否则数据缺失无法排查;② 重试的写操作要幂等(重试可能已部分生效);③ 谨慎定义跳过异常类型,别把严重错误也跳过。

    4. Spring Batch 有哪些并行处理方式?

    要点:四种。① 多线程 Step——单 Step 内多线程并行处理,要求 Reader/Processor/Writer 线程安全;② 并行 Step——用 Flow 让互不依赖的 Step 同时执行;③ 分区(Partitioning)——把大数据按键拆成子分区,各分区独立并行处理后汇总,适合可自然切分的数据;④ 远程分块——读在主节点、处理分发到多台机器(跨进程)。选择:单机内优先多线程/分区,步骤独立用并行 Step,超大规模跨机才用远程分块。

    5. 多线程 Step 的线程安全要注意什么?

    要点:并行处理时组件被多线程并发调用。Reader——必须支持并发读(线程安全的读取或内部加锁),否则重复读/漏读;Processor——保持无状态,不共享可变状态;Writer——批量写要支持并发提交,数据库操作注意连接与事务边界(每个线程各自的提交)。另外共享的聚合统计要线程安全。不满足会导致数据错乱、丢失、重复——并行化前必须逐一确认线程安全性。

    6. 分区(Partition)是怎么工作的?

    要点:把大任务按某个键(通常是主键范围或哈希)拆成多个互不重叠的子分区,每个分区分配给一个独立的工作线程/实例并行处理(各自有自己的 Reader 范围),全部完成后汇总。关键:① 分区逻辑要保证不重叠不遗漏;② 各分区数据独立、无交叉依赖;③ 分区数量决定并行度。适合百万~亿级可按键切分的数据。与多线程 Step 的区别:分区是数据切分后各自独立流,多线程是同一流程并发执行。

    7. 批处理任务怎么做监控告警?

    要点:数据源是执行元数据(状态、读写计数、耗时)+ 监听器钩子。建设:① 执行结果监控——成功/失败、执行时长(超阈值告警)、未按时触发告警;② 数据处理量监控——读写计数异常(为 0 或骤变告警);③ 跳过/失败明细——SkipListener 记录可查;④ 依赖与资源——数据源连接、磁盘(文件型任务)。落地:监听器上报指标到监控平台,调度平台提供失败告警与执行日历。批处理无人值守,监控必须完备。

    8. 批处理和在线服务共用数据库,怎么防止互相影响?

    要点:批处理大数据量读写会与在线请求争抢数据库资源(连接、IO、锁)。措施:① 时间错峰——批处理安排在在线低峰;② 限流——控制批处理的并发度与批量大小,避免打满连接池;③ 读写分离——批处理的大批量读走从库或专用只读实例,写控制速率;④ 独立连接池——批处理与在线分池,互不抢占;⑤ 必要时独立库/资源组隔离。原则:批处理是"可延时的",在线是"必须保障的",资源分配向在线倾斜。

    9. 如何防止批处理任务被并发重复触发?

    要点:多层防护。① 框架层——同一 JobInstance(同参数)已在运行/完成时,再次启动被拒绝(元数据表实例唯一性约束);② 调度层——调度平台配置互斥执行(上一次未完成不触发下一次);③ 应用层——分布式场景加分布式锁(防多实例同时触发);④ 参数设计——用唯一参数标识每次运行,避免歧义。核心是"同一逻辑运行只执行一次",与在线接口的幂等防重思想一致。

    10. 什么时候该用 Spring Batch,什么时候直接用消息队列?

    要点:按数据形态与时效。Spring Batch 适合:有明确数据集(文件/表)、批量加工、需要进度跟踪与断点续跑、离线窗口执行——强调"处理完这批数据"。消息队列适合:持续流入的事件、实时/准实时处理、削峰、解耦——强调"来一条处理一条"。也可组合:队列积压的事件攒成批,用批处理框架定时消费(如 Spark/批任务拉取)。选择标准:批量边界清晰、需重跑与进度管理用 Batch;流式、低延迟用消息。

    在这里插入图片描述

    赞(0)
    未经允许不得转载:171主机测评 » Spring Batch 高级特性与实践详解
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址