日常梳理-Spring Batch

1.Spring Batch

Spring Batch是一个轻量级的批处理框架,用于开发企业级批处理应用程序。

2.基本概念

  • Job: 批处理作业,由多个步骤(Step)组成
  • Step: 作业的步骤,包含 ItemReader、ItemProcessor 和 ItemWriter
  • ItemReader: 读取数据
  • ItemProcessor: 处理数据
  • ItemWriter: 写入数据

任务监听器:在 Job 配置中添加监听器

合理设置 chunk size(处理块大小)

3.Step

3.1 chunkSize

核心作用

  1. 控制事务边界

    • 事务提交频率:每处理完 chunkSize 数量的记录后提交一次事务

    • 失败恢复粒度:如果作业失败,可以恢复到上一个成功提交的 chunk 边界

      示例:chunkSize=100 表示每处理100条记录提交一次事务

  2. 影响内存使用

    • 内存缓冲:Spring Batch 会在内存中累积 chunkSize 数量的记录,然后一次性交给 Writer 处理

    • 大chunkSize:提高处理效率但增加内存压力

    • 小chunkSize:降低内存使用但增加I/O操作

  3. 决定批处理性能

    • 数据库操作: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 的具体作用

  1. 决定分区数量:gridSize 指定了要将作业分成多少个并行执行的分区

    例如设置为10,则会创建10个独立的分区,每个分区处理一部分数据

  2. 影响并行度:与 TaskExecutor 的线程池大小共同决定实际并行执行的任务数量

    实际并行度 = min(gridSize, 线程池大小)

  3. 分区策略配合与 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)逻辑处理错误

使用事务管理确保数据一致性

考虑使用异步步骤提高性能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值