文章目录
1.Spring Batch
Spring Batch是一个轻量级的批处理框架,用于开发企业级批处理应用程序。
2.基本概念
- Job: 批处理作业,由多个步骤(Step)组成
- Step: 作业的步骤,包含 ItemReader、ItemProcessor 和 ItemWriter
- ItemReader: 读取数据
- ItemProcessor: 处理数据
- ItemWriter: 写入数据
任务监听器:在 Job 配置中添加监听器
合理设置 chunk size(处理块大小)
3.Step
3.1 chunkSize
核心作用
-
控制事务边界
-
事务提交频率:每处理完 chunkSize 数量的记录后提交一次事务
-
失败恢复粒度:如果作业失败,可以恢复到上一个成功提交的 chunk 边界
示例:chunkSize=100 表示每处理100条记录提交一次事务
-
-
影响内存使用
-
内存缓冲:Spring Batch 会在内存中累积 chunkSize 数量的记录,然后一次性交给 Writer 处理
-
大chunkSize:提高处理效率但增加内存压力
-
小chunkSize:降低内存使用但增加I/O操作
-
-
决定批处理性能
-
数据库操作:Writer 通常是批量操作(如JDBC批量插入),chunkSize 决定批量操作的大小
-
网络开销:对于远程服务调用,较大的 chunkSize 可以减少调用次数
-
工作原理
读取阶段(Reader) → 处理阶段(Processor) → 累积到chunkSize → 写入阶段(Writer) → 事务提交
↑_________________________________________________________|
3.2.使用分区(Partitioning)处理大数据集
@Bean
public Step partitionStep() {
return stepBuilderFactory.get("partitionStep")
.partitioner("slaveStep", partitioner())
.gridSize(10) // 这里设置gridSize
.taskExecutor(taskExecutor())
.build();
}
@Bean
public TaskExecutor taskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10); // 与gridSize协调
executor.setMaxPoolSize(10);
executor.setThreadNamePrefix("batch-");
return executor;
}
gridSize 的具体作用
-
决定分区数量:gridSize 指定了要将作业分成多少个并行执行的分区
例如设置为10,则会创建10个独立的分区,每个分区处理一部分数据
-
影响并行度:与 TaskExecutor 的线程池大小共同决定实际并行执行的任务数量
实际并行度 = min(gridSize, 线程池大小)
-
分区策略配合:与 Partitioner 接口实现配合使用,Partitioner 的 partition() 方法会接收到这个gridSize值
可以基于gridSize来决定如何划分数据范围
gridSize与chunkSize的区别
gridSize 影响的是作业的横向扩展能力(并行处理多个分区);
而 chunkSize 影响的是单个任务内部的批处理粒度(每次事务处理多少条记录)。
参数 | 作用范围 | 目的 | 典型值 |
---|---|---|---|
gridSize | 分区步骤 | 控制并行任务数量 | CPU核心数1-2倍 |
chunkSize | 单个步骤内 | 控制事务提交频率 | 10-1000 |
4.使用分页
JdbcPagingItemReader (基于JDBC的分页)
@Bean
public JdbcPagingItemReader<Customer> pagingItemReader(DataSource dataSource,
PagingQueryProvider queryProvider) {
Map<String, Object> parameterValues = new HashMap<>();
parameterValues.put("status", "ACTIVE");
return new JdbcPagingItemReaderBuilder<Customer>()
.name("customerReader")
.dataSource(dataSource)
.queryProvider(queryProvider)
.parameterValues(parameterValues)
.pageSize(100) // 每页大小
.rowMapper(new BeanPropertyRowMapper<>(Customer.class))
.build();
}
@Bean
public SqlPagingQueryProviderFactoryBean queryProvider(DataSource dataSource) {
SqlPagingQueryProviderFactoryBean provider = new SqlPagingQueryProviderFactoryBean();
provider.setDataSource(dataSource);
provider.setSelectClause("SELECT id, name, email");
provider.setFromClause("FROM customer");
provider.setWhereClause("WHERE status = :status");
provider.setSortKey("id"); // 排序字段,必须保证唯一性
return provider;
}
实现跳过(Skip)和重试(Retry)逻辑处理错误
使用事务管理确保数据一致性
考虑使用异步步骤提高性能