在 Spring Batch Step、Tasklet 或 Chunks 之间做出决定
Posted
技术标签:
【中文标题】在 Spring Batch Step、Tasklet 或 Chunks 之间做出决定【英文标题】:Deciding between Spring Batch Step, Tasklet or Chunks 【发布时间】:2013-06-13 04:10:40 【问题描述】:我有一个直截了当的要求,我需要(从 DB)读取项目列表并需要处理这些项目,一旦处理,它必须更新到 DB。
我正在考虑使用带有读取器、处理器和写入器的 Spring 批处理块。我的阅读器将一次从列表中返回一个项目并将其发送到处理器,一旦处理结束,它会返回到 Writer 并更新数据库
稍后我可能会在这些方法中以一些同步成本对其进行多线程处理。
在这里我预见到一些问题。
-
要处理的项目数可能更多。可能有 10,000 甚至更多。
处理器中需要进行一些逻辑计算。因此一次处理 1 个项目。即使它是 10 线程的多线程,也不确定性能。
Writer 可以更新数据库中该已处理项目的结果。不确定如何进行批量更新,因为它始终只有 1 项已处理并准备就绪。
这种方法对于这种用例是否正确,或者可以做任何更好的事情吗? 有没有其他方法可以在一次读取器、处理器和写入器的调用中处理一堆项目?如果是这样,我是否需要创建一些机制,从列表中提取 10 个项目并将其提供给处理器? 似乎作者更新了每条记录,只有当作者收到一堆已处理的项目时,批量更新才有意义。有什么建议吗?
为了更好的性能,请对该设计进行一些说明。
谢谢,
【问题讨论】:
【参考方案1】:Spring Batch 是满足您需要的完美工具。
面向块的步骤让您可以使用 commit-interval 属性配置要读取/处理/写入的项目数。
<batch:step id="step1" next="step2">
<batch:tasklet transaction-manager="transactionManager" start-limit="100">
<batch:chunk reader="myReader" processor="myProcessor" writer="MyWriter" commit-interval="800" />
<batch:listeners>
<batch:listener ref="myListener" />
</batch:listeners>
</batch:tasklet>
</batch:step>
假设您的读者将调用返回 10 000 条记录的 SELECT 语句。你设置了一个 commit-interval=500。
MyReader 将调用 read() 方法 500 次。假设实际上,阅读器实现实际上可能会从结果集中删除项目。对于每次调用 read(),它还会调用 MyProcessor 的 process() 方法。
但它不会调用 MyWriter 的 write() 方法,直到达到 commit-interval。
如果看接口ItemWriter的定义:
public interface ItemWriter<T>
/**
* Process the supplied data element. Will not be called with any null items
* in normal operation.
*
* @throws Exception if there are errors. The framework will catch the
* exception and convert or rethrow it as appropriate.
*/
void write(List<? extends T> items) throws Exception;
您会看到 write 收到一个项目列表。此列表将是您的提交间隔的大小(如果到达末尾,则更少)
顺便说一句,10 000 条记录不算什么。如果您必须处理数百万条记录,您可以考虑使用多线程。但即便如此,仅仅使用 commit-interval 值的最佳位置可能就足够了。
希望对你有帮助
【讨论】:
非常感谢您的建议。真的很有帮助。 你能指导***.com/questions/36391219/…吗?以上是关于在 Spring Batch Step、Tasklet 或 Chunks 之间做出决定的主要内容,如果未能解决你的问题,请参考以下文章
Spring Batch - 为啥在 Web 上下文而不是 Job 上下文中创建/执行作业 Step bean?
Spring Batch - 如何使用一个读取其他步骤的作者的并行步骤?