Spring Batch:哪个ItemReader实现用于高容量&低延迟

时间:2013-12-04 21:42:30

标签: spring jdbc batch-processing spring-batch

用例:从数据库中读取1000万行[10列]并写入文件(csv格式)。

  1. JdbcCursorItemReader &中的哪个ItemReader实现会建议 JdbcPagingItemReader 吗?那是什么原因?

  2. 在上述用例中表现更好(快)?

  3. 在单流程与多流程方法的情况下,选择是否会有所不同?

  4. 如果是使用TaskExecutor的多线程方法,哪一个会更好&简单

2 个答案:

答案 0 :(得分:9)

要处理这种数据,如果可能的话,你可能想要并行化它(如果输出文件需要保留输入的顺序,那么唯一阻止它的是)。假设您要对您的处理进行并行化,那么您将为此类用例提供两个主要选项(根据您提供的内容):

  1. 多线程步骤 - 这将处理每个线程的块,直到完成。这允许以非常简单的方式进行并行化(只需在步骤定义中添加TaskExecutor)。有了这个,你就可以开箱即用了松散的可重启性,因为你需要在你提到的任何一个ItemReader上关闭状态持久性(有很多方法可以将数据库中的记录标记为已处理等)。
  2. 分区 - 将输入数据分解为并行的步骤实例处理的分区(主/从配置)。分区可以通过线程(通过TaskExecutor)在本地执行,也可以通过远程分区远程执行。在任何一种情况下,您都可以通过并行化获得可重启性(每个步骤都处理它自己的数据,因此从分区到分区没有踩到状态)。
  3. 我与Spring Batch并行处理数据。具体来说,我提供的示例是远程分区作业。您可以在此处查看:https://www.youtube.com/watch?v=CYTj5YT7CZU

    针对您的具体问题:

    1. JdbcCursorItemReader&中的哪个ItemReader实现;会建议使用JdbcPagingItemReader吗?原因是什么? - 可以调整这两个选项中的任何一个以满足许多性能需求。这实际上取决于您正在使用的数据库,可用的驱动程序选项以及您可以支持的处理模型。另一个考虑因素是,你需要重新启动吗?
    2. 在上述用例中表现更好(快)? - 再次取决于您选择的处理模型。
    3. 在单进程与多进程方法的情况下,选择是否会有所不同? - 这比Spring Batch可以处理的更多地管理作业。问题是,您是要管理作业外部的分区(将数据描述作为参数传递给作业)还是希望作业管理它(通过分区)。
    4. 如果是使用TaskExecutor的多线程方法,哪一个会更好&简单? - 我不会否认远程分区会增加本地分区和多线程步骤所没有的复杂程度。
    5. 我从基本步骤定义开始。然后尝试多线程步骤。如果这不符合您的需求,则转到本地分区,最后根据需要进行远程分区。请记住,Spring Batch旨在使这种进展尽可能轻松。只需配置更新,您就可以从常规步骤转到多线程步骤。要进行分区,您需要添加一个新类(Partitioner实现)和一些配置更新。

      最后一点说明。其中大部分讨论了并行处理这些数据。 Spring Batch的FlatFileItemWriter 线程安全。您最好的选择是并行写入多个文件,然后如果速度是您的头号问题,则将它们聚合在一起。

答案 1 :(得分:7)

您应该对此进行分析以便做出选择。在简单的JDBC中,我会从以下内容开始:

  • 使用ResultSet.TYPE_FORWARD_ONLYResultSet.CONCUR_READ_ONLY准备语句。除非你使用这两个游标,否则几个JDBC驱动程序会在客户端“模拟”游标,对于大型结果集你不需要它,因为它可能会导致你OutOfMemoryError因为你的JDBC驱动程序在缓冲整个数据集记忆。通过使用这些选项,您可以增加获得服务器端游标的机会,并将结果“流式传输”到您的位置,这就是您想要的大型结果集。请注意,某些JDBC驱动程序始终“模拟”客户端中的游标,因此此提示可能对您的特定DBMS无用。
  • 设置合理的fetch size以尽量减少网络往返的影响。 50-100通常是分析的良好起始值。由于提取大小是提示,这对您的特定DBMS也可能没用。

JdbcCursorItemReader似乎涵盖了这两个方面,但正如之前所说的那样,它们无法保证在所有DBMS中为您提供最佳性能,因此我将从那开始,然后,如果性能不足,请尝试{{ 3}}

除非您有非常严格的性能要求,否则我认为使用JdbcCursorItemReader进行简单处理对您的数据集大小来说会很慢。如果确实需要使用JdbcPagingItemReader进行并行化可能更容易,但这两者的界面非常相似,所以我不会指望它。

无论如何,个人资料