Spring 多线程与分区之间的批处理差异

Spring batch difference between Multithreading vs partitioning

我无法理解 Spring 批处理中多线程和分区的区别。实现当然是不同的:在分区中你需要准备分区然后处理它。我想知道有什么区别,当瓶颈是项目处理器时,哪种处理方式更有效。

TL;DR;
当处理器出现瓶颈时,这两种方法都无济于事。通过让多个项目同时通过处理器,您会看到一些好处,但是您指出的两个选项在 I/O 绑定的进程中使用时都能获得全部好处。 AsyncItemProcessor/AsyncItemWriter 可能是更好的选择。

Spring 批处理可扩展性概述
缩放 Spring 批处理作业有五个选项:

  1. 多线程步骤
  2. 平行步骤
  3. 分区
  4. 远程分块
  5. AsyncItemProcessor/AsyncItemWriter

每个都有自己的优点和缺点。让我们逐一浏览:

多线程步骤
多线程步骤采用单个步骤并在单独的线程上执行该步骤中的每个块。这意味着每个批处理组件(读取器、写入器等)的相同实例在线程之间共享。在大多数情况下,这可以通过以可重启性为代价向步骤添加一些并行性来提高性能。你牺牲了可重启性,因为在大多数情况下,重启的能力是基于 reader/writer/etc 中维护的状态。随着多个线程更新该状态,它变得无效且无法重新启动。因此,您通常需要关闭单个组件的保存状态,并将作业的可重启标志设置为 false。

平行步骤
并行步骤是通过拆分实现的。它允许您通过线程并行执行多个独立的步骤。这不会牺牲可重启性,但无助于提高单个步骤或业务逻辑的性能。

分区
分区是预先通过主步骤将数据划分为更小的块(称为分区),然后让从属在分区上独立工作。在 Spring Batch 中,master 和每个 slave 都是一个独立的步骤,因此您可以在不牺牲可重启性的情况下在单个步骤中获得并行性的好处。分区还提供了扩展到单个 JVM 之外的能力,因为从属不必是本地的(您可以使用各种通信机制与远程从属通信)。

关于分区的一个重要注意事项是主从之间的唯一通信是数据的描述,而不是数据本身。例如,master可能会告诉slave1处理1-100条记录,slave2处理101-200条记录等。master不发送实际数据,只发送slave获取它应该处理的数据所需的信息.因此,数据必须在从属进程的本地,而主进程可以位于任何地方。

远程分块
远程分块允许您跨 JVM 扩展进程和可选的写入逻辑。在此用例中,主机读取数据,然后通过线路将其发送到从机,在那里处理数据,然后在本地写入从机或返回主机以在本地写入主机。

分区和远程分块之间的重要区别在于,远程分块发送实际数据,而不是通过网络传输描述通过电线。因此,远程分块将发送实际记录 1-100,而不是单个数据包说进程记录 1-100。这会对步骤的 I/O 配置文件产生很大影响,但如果处理器足以成为瓶颈,这可能会有用。

AsyncItemProcessor/AsyncItemWriter
缩放 Spring 批处理的最后一个选项是 AsyncItemProcessor/AsycnItemWriter 组合。在这种情况下,AsyncItemProcessor 包装您的 ItemProcessor 实现并在单独的线程中执行对您的实现的调用。 AsyncItemProcessor 然后 returns 传递给 AsyncItemWriterFuture 在那里它被解包并传递给委托 ItemWriter 实现。

由于数据流经此选项的方式的性质,某些侦听器场景不受支持(因为我们不知道 ItemProcessor 调用的结果,直到在 ItemWriter 内部)但是总的来说,它可以提供一个有用的工具,用于在不牺牲可重启性的情况下仅在单个 JVM 中并行化 ItemProcessor 逻辑。