Skip to content

⚙️ Spring Batch 重试逻辑配置指南

核心要义:在批处理中,非确定性异常可通过重试解决,而确定性异常重试无效!

🧠 为什么需要重试机制?

异常类型对比

异常类型特点是否适合重试典型场景
确定性异常相同操作必然发生❌ 不适合FlatFileParseException
(文件解析错误)
非确定性异常由临时状态引起✅ 适合DeadlockLoserDataAccessException
(数据库死锁)

🛠️ Kotlin 配置实战

基础重试配置

kotlin
@Configuration
@EnableBatchProcessing
class BatchConfig {

    @Bean
    fun step1(jobRepository: JobRepository,
              transactionManager: PlatformTransactionManager): Step {
        return StepBuilder("step1", jobRepository)
            .chunk<String, String>(10, transactionManager)
            .reader(myItemReader())
            .processor(myItemProcessor())
            .writer(myItemWriter())
            .faultTolerant()  // 启用容错机制
            .retryLimit(3)    // 最大重试次数
            .retry(DeadlockLoserDataAccessException::class.java)  // 指定重试异常
            .build()
    }

    // 其他bean定义...
}

多异常类型重试

kotlin
// 在step配置中添加:
.retryLimit(5)
.retry(DeadlockLoserDataAccessException::class)
.retry(OptimisticLockingFailureException::class)
.retry(ConcurrencyFailureException::class)

WARNING

危险配置警告
避免对确定性异常配置重试!以下配置会导致无效重试循环:

kotlin
.retry(FlatFileParseException::class)  

⚡ 高级配置技巧

指数退避策略

kotlin
// 添加重试策略配置
val retryPolicy = SimpleRetryPolicy().apply {
    maxAttempts = 5
}

val backOffPolicy = ExponentialBackOffPolicy().apply {
    initialInterval = 1000  // 初始间隔1秒
    multiplier = 2.0       // 指数倍数
    maxInterval = 10000    // 最大间隔10秒
}

return StepBuilder("advancedStep", jobRepository)
    .chunk<String, String>(10, transactionManager)
    .faultTolerant()
    .retryPolicy(retryPolicy)
    .backOffPolicy(backOffPolicy)   // 设置退避策略
    .build()

自定义重试决策器

kotlin
class CustomRetryDecider : RetryPolicy {

    override fun canRetry(context: RetryContext): Boolean {
        val ex = context.lastThrowable
        // 仅重试特定错误码的异常
        return (ex is MyBusinessException && ex.errorCode == "RETRYABLE")
    }
}

// 在Step中使用:
.retryPolicy(CustomRetryDecider())

🚨 关键注意事项

性能警告

过度重试会导致批处理作业严重延迟!建议:

  1. 设置合理的重试上限(通常3-5次)
  2. 结合监控告警机制
  3. 避免在写入操作中重试整个chunk

最佳实践

  1. 隔离重试逻辑:为不同操作配置不同重试策略
kotlin
// 仅为写入操作配置重试
writer(myItemWriter())
    .faultTolerant()
    .retryLimit(3)
    .retry(DataAccessException::class)
  1. 结合跳过机制:重试失败后跳过当前记录而非终止作业
kotlin
.retryLimit(3)
.skipLimit(10)  // 允许跳过10条记录
.skip(DeadlockLoserDataAccessException::class)

🔍 深度解析:重试工作原理

IMPORTANT

核心机制
Spring Batch的重试是基于单条记录的,而非整个chunk。每次重试都会:

  1. 回滚当前事务
  2. 重新处理相同记录
  3. 独立计数每条记录的重试次数

💎 总结

配置要素推荐方案工具方法
重试异常类型非确定性异常.retry(异常类)
重试次数3-5次.retryLimit(次数)
重试间隔指数退避策略.backOffPolicy()
失败处理结合跳过机制.skipLimit().skip()
监控记录重试日志 + 告警RetryListener 接口实现
kotlin
@Bean
fun robustStep(jobRepository: JobRepository,
               txManager: PlatformTransactionManager): Step {
    return StepBuilder("secureStep", jobRepository)
        .chunk<Data, Result>(5, txManager)
        .reader(dbItemReader())
        .processor(validationProcessor())
        .writer(jdbcWriter())
        .faultTolerant()
        .retryLimit(3)
        .retry(DeadlockLoserDataAccessException::class)
        .retry(TransientDataAccessException::class)
        .skipLimit(100)
        .skip(DataIntegrityViolationException::class)
        .listener(retryMonitoringListener())  // 监控监听器
        .build()
}

行动建议
立即检查你的批处理作业,为这些异常添加重试支持:

  1. DeadlockLoserDataAccessException
  2. OptimisticLockingFailureException
  3. QueryTimeoutException
  4. SocketException(网络操作时)