跳过 SpringBatch 分区中的"Serialization/Deserialization",将数据复制扩展到百万条记录



我正在使用Spring Batch Partitioning策略来设置ETL过程(将数据从一个数据库复制到另一个数据库(,可能只有几百万条记录。

当我将输入有效负载大小增加到100万以上时,进程会因内存不足而失败(使用14GB RAM进行测试(。经过分析,我发现SpringBatch正在创建有效的byte[]和String对象,它们占据了相当大的内存。这些对象是由MapStepExecutionDao类创建的,同时尝试为每个分区保存StepExecution。以下是呼叫流程:

org.springframework.util.SerializationUtils.serialize(对象(org.springframework.batch.core.repository.doo.MapStepExecutionDao.copy(StepExecution(org.springframework.batch.core.repository.doo.MapStepExecutionDao.saveStepExecution(StepExecution(org.springframework.batch.core.repository.doo.MapStepExecutionDao.saveStepExecutions(Collection(org.springframework.batch.core.restore.support.SimpleJobRepository.addAll(Collection(

在这种情况下,StepExecution中的ExecutionContext有一个大字符串(格式为"abc,def,…………..xyz"(,由于表结构,我不得不将其用作查询数据的输入。MapStepExecutionDao.copy序列化然后反序列化StepExecution对象以创建其副本。是否有方法跳过StepExecution的"序列化/反序列化"以获得其副本,因为它正在创建额外的字节[]和字符串,这些字节和字符串占用了大量堆,并且堆消耗随着输入大小的增加而增加(比我预期的要多(。

私有静态StepExecution副本(StepExecution原件({return(StepExecution(SerializationUtils.deserialize(SerializationUtils.serialize(original((;}

请让我知道

  • 如果有办法跳过StepExecution的"序列化/反序列化">
  • SpringBatch中是否有任何配置可以避免"序列化/反序列化">
  • 是否有方法扩展/覆盖此行为

这是基于Map的DAO的一个已知问题。这也是我们决定弃用它们的原因之一,请参阅https://github.com/spring-projects/spring-batch/issues/3780.

建议的替换方法是将基于JDBC的作业存储库与内存中的数据库一起使用。我在上面分享的问题包含一个基准,您可以使用它来测试性能改进。

最新更新