原文:https://blog.codecentric.de/en/2012/03/transactions-in-spring-batch-part-3-skip-and-retry/

This is the third post in a series about transactions in Spring Batch, you find the first one here, it’s about the basics, and the second one here, it’s about restart, cursor based reading and listeners.
Today’s topics are skip and retry functionality, and how they behave regarding transactions. With the skip functionality you may specify certain exception types and a maximum number of skipped items, and whenever one of those skippable exceptions is thrown, the batch job doesn’t fail but skip the item and goes on with the next one. Only when the maximum number of skipped items is reached, the batch job will fail. However, whenever there’s a skip, we still want to roll back the transaction, but only for that one skipped item. Normally we have more than one item in a chunk, so how does Spring Batch accomplish that? With the retry functionality you may specify certain retryable exceptions and a maximum number of retries, and whenever one of those retryable exceptions is thrown, the batch job doesn’t fail but retries to process or write the item. Same question here, we still need a rollback for the failed item if a try fails, and a rollback includes all items in the chunk. Let’s see.

Skip

As you might know, there are two ways of specifying skip behaviour in Spring Batch. They don’t make a difference regarding transactions. The convenient standard way would be specifying a skip-limit on the chunk and nesting skippable-exception-classes inside the chunk:

 
<batch:tasklet>
<batch:chunk reader="myItemReader" writer="myItemWriter" commit-interval="20" skip-limit="15">
<batch:skippable-exception-classes>
<batch:include class="de.codecentric.MySkippableException" />
</batch:skippable-exception-classes>
</batch:chunk>
</batch:tasklet>

And if you need a more sophisticated skip-checking, you may implement the SkipPolicy interface and plug your own policy into your chunkskip-limit and skippable-exception-classes are ignored then:

 
<batch:tasklet>
<batch:chunk reader="myItemReader" writer="myItemWriter" commit-interval="20" skip-policy="mySkipPolicy"/>
</batch:tasklet>

Let’s get to the transactions now, again with the illustration. First we’ll have a look at a skip in an ItemProcessor.

So, if you get a skippable exception (or your SkipPolicy says it’s a skip), the transaction will be rolled back. Spring Batch caches the items that have been read in, so now the item that led to the failure in the ItemProcessor is excluded from that cache. Spring Batch starts a new transaction and uses the now reduced cached items as input for the process phase. If you configured a SkipListener, its onSkipInProcess method will be called with the skipped item right before committing the chunk. If you configured a skip-limit that number is checked on every skippable exception, and when the number is reached, the step fails.
What does that mean? It means that you might get into trouble if you have a transactional reader or do the mistake of doing anything else than reading during the reading phase. A transactional reader for example is a queue, you consume one message from a queue, and if the transaction is rolled back, the message is put back in the queue. With the caching mechanism shown in the illustration, messages would be processed twice. The Spring Batch guys added the possibility to mark the reader as transactional by setting the attribute reader-transactional-queue on the chunk to true. Done that the illustration would look different, because items would be re-read.
Even if you don’t have a transactional reader you might get into trouble. For example, if you define a ItemReadListener to protocol items being read somewhere in a transactional resource, then those protocols get rolled back as well, even though all but one item are processed successful.

It gets even more complicated when we have a skip during writing. Since the writer is just called once with all items, the framework does not know which item caused the skippable exception. It has to find out. And the only way to find out is to split the chunk into small chunks containing just one item. Let’s have a look at the slightly more complicated diagram.

We now get a second loop, indicated with the red colour. It starts with a skippable exception in our normal chunk, leading to a rollback (the yellow line). Now the framework has to find out, which item caused the failure. For each item in the cached list of read items it starts an own transaction. The item is processed by the ItemProcessor and then written by the ItemWriter. If there is no error, the mini-chunk with one item is committed, and the iteration goes on with the next item. We expect at least one skippable exception, and when that happens, the transaction is rolled back and the item is marked as skipped item. As soon as our iteration is complete, we continue with normal chunk processing.
I think I don’t need to mention that the problems with transactional readers apply here as well. In addition, it is possible to mark the processor as non-transactional by setting the attribute processor-transactional on the chunk to false (its default is true). If you do that, Spring Batch caches processed items and doesn’t re-execute the ItemProcessor on a write failure. You just can do that if there is no writing interaction with a transactional resource in the processing phase, otherwise processings get rolled back on a write failure but are not re-executed.

One more thing: what about skipping during reading? I didn’t do a diagram for that, because it’s quite simple: when a skippable exception occurs during reading, we just increase the skip count and keep the exception for a later call on the onSkipInReadmethod of the SkipListener, if configured. There’s no rollback.

Retry

As with the skip functionality, there are two ways of specifying retry behaviour in Spring Batch. The convenient standard way would be specifying a retry-limit on the chunk and nesting retryable-exception-classes inside the chunk:

 
<batch:tasklet>
<batch:chunk reader="myItemReader" writer="myItemWriter" commit-interval="20" retry-limit="15">
<batch:retryable-exception-classes>
<batch:include class="de.codecentric.MyRetryableException" />
</batch:retryable-exception-classes>
</batch:chunk>
</batch:tasklet>

As with skipping, you may specify your own RetryPolicy and plug it into the chunk:

 
<batch:tasklet>
<batch:chunk reader="myItemReader" writer="myItemWriter" commit-interval="20" retry-policy="myRetryPolicy"/>
</batch:tasklet>

Let’s take a look at the diagram for retrying.

Whenever during processing or writing a retryable exception occurs, the chunk is rolled back. Spring Batch checks if the maximum number of retries is exceeded, and if that’s the case, the step fails. If that’s not the case, all items that have been read before are input for the next process phase. Basically, all limitations that apply to skipping items apply here as well. And we can apply modifications to the transactional behaviour via using reader-transactional-queue and processor-transactional in the same manner.
One important thing: at the time of writing (Spring Batch 2.1.8) there is a bug with a failure during writing. If there’s a retryable exception during writing only the first item gets reprocessed, all other items in the cached list of read item are not reprocessed (https://jira.springsource.org/browse/BATCH-1761).

Conclusion

Spring Batch is a great framework offering functionality for complex processings like skipping or retrying failed items, but you still need to understand what Spring Batch does to avoid problems. In this article we saw potential stumbling blocks when using skip and retry functionality.

Spring Batch的事务– Part 3: 略过和重试的更多相关文章

  1. Spring Batch的事务-Part 1:基础

    原文 https://blog.codecentric.de/en/2012/03/transactions-in-spring-batch-part-1-the-basics/ This is th ...

  2. Spring Batch在大型企业中的最佳实践

    在大型企业中,由于业务复杂.数据量大.数据格式不同.数据交互格式繁杂,并非所有的操作都能通过交互界面进行处理.而有一些操作需要定期读取大批量的数据,然后进行一系列的后续处理.这样的过程就是" ...

  3. 初探Spring Batch

    此系列博客皆为学习Spring Batch时的一些笔记: 为什么我们需要批处理? 我们不会总是想要立即得到需要的信息,批处理允许我们在请求处理之前就一个既定的流程开始搜集信息:比如说一个银行对账单,我 ...

  4. Spring Batch 中文参考文档 V3.0.6 - 1 Spring Batch介绍

    1 Spring Batch介绍 企业领域中许多应用系统需要采用批处理的方式在特定环境中运行业务操作任务.这种业务作业包括自动化,大量信息的复杂操作,他们不需要人工干预,并能高效运行.这些典型作业包括 ...

  5. Spring Batch 批处理框架

    <Spring Batch 批处理框架>基本信息作者: 刘相 出版社:电子工业出版社ISBN:9787121252419上架时间:2015-1-24出版日期:2015 年2月开本:16开页 ...

  6. Spring Batch实践

    Spring Batch在大型企业中的最佳实践 在大型企业中,由于业务复杂.数据量大.数据格式不同.数据交互格式繁杂,并非所有的操作都能通过交互界面进行处理.而有一些操作需要定期读取大批量的数据,然后 ...

  7. spring batch学习笔记

    Spring Batch是什么?       Spring Batch是一个基于Spring的企业级批处理框架,按照我师父的说法,所有基于Spring的框架都是使用了spring的IoC特性,然后加上 ...

  8. 图书简介:Spring Batch批处理框架

    大数据时代批处理利器,国内首度原创解析Spring Batch框架. 内容简介: <Spring Batch 批处理框架>全面.系统地介绍了批处理框架Spring Batch,通过详尽的实 ...

  9. Maven+Spring Batch+Apache Commons VF学习

    Apache Commons VFS资料:例子:http://www.zihou.me/html/2011/04/12/3377.html详细例子:http://p7engqingyang.iteye ...

随机推荐

  1. rqnoj-106-最大加权矩形-dp

    和我之前做的那个切西瓜的题目相比就是小巫见大巫了.. 运用最长字段和的原理把O(n^4)转化成O(n^3) #include<stdio.h> #include<string.h&g ...

  2. ffmpeg mp4转yuv

    mp4转yuv ffmpeg -i test.mp4 test.yuv 播放yuv ffplay.exe -f rawvideo -video_size 1280x720 -i test.yuv

  3. easyui validatebox 验证集合

    <html xmlns="http://www.w3.org/1999/xhtml"> <head> <script src="easyui ...

  4. ACM - ICPC World Finals 2013 I Pirate Chest

    原题下载:http://icpc.baylor.edu/download/worldfinals/problems/icpc2013.pdf 题目翻译: 问题描述 海盗Dick受够了在公海上厮杀.抢劫 ...

  5. Bootstrap介绍以及配置

    一.Bootstrap概述: 1.Bootstrap 是基于 HTML.CSS.JAVASCRIPT 的一个用于快速开发 Web 应用程序和网站的前端框架. 2.用于开发响应式布局.移动设备优先的 W ...

  6. UVa 1607 (二分) Gates

    这道题真的有点“神”啊.= ̄ω ̄= 因为输入都是x,所以整个电路的功能一共就四种:0, 1, x,!x 所以就确定了这样一个事实:如果电路的输出是常数,那么所有的输入都可以优化成常数. 否则,只需要将 ...

  7. factory工厂模式

    工厂方法模式 工厂方法模式概述    工厂方法模式中抽象工厂类负责定义创建对象的接口,具体对象的创建工作由继承抽象工厂的具体类实现 简单理解: 与简单工厂模式类似,简单工厂模式是一个工厂,用户将条件为 ...

  8. RequireJS入门(二) 转

    上一篇是把整个jQuery库作为一个模块.这篇来写一个自己的模块:选择器. 为演示方便这里仅实现常用的三种选择器id,className,attribute.RequireJS使用define来定义模 ...

  9. 【转】ios开发之AppDelegate

    创建应用程序之后之后,默认有AppDelegate.h文件与AppDelegate.m文件.   AppDelegate为何物?  AppDelegate为整个应用的一个代理,提供程序启动.退出等类似 ...

  10. 【javascript】js 判断微信浏览器

    上周接到个需求,需求是这样的:用户扫一扫二维码会产生一个链接,该链接会向后端发送个请求,返回一个 apk 的下载地址,用户点击下载按钮可以下载此 apk.然后就发生了问题,经过测试,发现用微信扫一扫打 ...