본문으로 건너뛰기
Advertisement

실전 고수 팁 — 처리 속도 향상을 위한 멀티스레딩과 병렬처리

단일 스레드로 동작하는 Spring Batch의 기본 설정에서는 5억 건의 레코드를 처리하려면 수 시간이 걸릴 수 있습니다. 아래 3가지 병렬화 전략을 통해 배치 처리 속도를 획기적으로 향상시킬 수 있습니다.

1. Multi-threaded Step (단순 멀티스레딩)

가장 먼저 시도할 것은 Step 자체에 TaskExecutor를 주입하여 청크를 병렬 스레드로 처리하는 방식입니다.

@Bean
public Step parallelChunkStep() {
return new StepBuilder("parallelChunkStep", jobRepository)
.<Coupon, Coupon>chunk(1000, transactionManager)
.reader(couponItemReader()) // ★ Thread-safe한 Reader여야 합니다 (JdbcPagingItemReader 권장)
.processor(couponItemProcessor())
.writer(couponItemWriter())
.taskExecutor(new SimpleAsyncTaskExecutor()) // 청크마다 별도 스레드
.throttleLimit(8) // 최대 동시 스레드 수
.build();
}
경고

Multi-threaded Step에서는 ItemReader가 반드시 Thread-safe해야 합니다. JdbcCursorItemReader는 Thread-safe하지 않으므로 SynchronizedItemStreamReader로 감싸거나, Thread-safe한 JdbcPagingItemReader를 사용하세요.

2. Parallel Steps (병렬 Step 실행)

서로 의존성이 없는 Step들을 동시에 실행하고 싶을 때 Flowsplit()를 활용합니다.

@Bean
public Job parallelStepsJob() {
// Step1, Step2를 독립적으로 동시에 실행
Flow flow1 = new FlowBuilder<SimpleFlow>("flow1")
.start(processEmailsStep())
.build();
Flow flow2 = new FlowBuilder<SimpleFlow>("flow2")
.start(processSmsStep())
.build();

Flow parallelFlow = new FlowBuilder<SimpleFlow>("parallelFlow")
.split(new SimpleAsyncTaskExecutor())
.add(flow1, flow2) // 두 Flow를 병렬 실행
.build();

return new JobBuilder("parallelStepsJob", jobRepository)
.start(parallelFlow)
.end()
.build();
}

3. Partitioning (파티셔닝 — 데이터 범위를 분할 후 병렬 처리)

전체 데이터를 여러 파티션(범위)으로 나누고 각 파티션을 별도 Worker Step이 독립적으로 처리하는 가장 강력한 병렬화 기법입니다.

@Bean
public Step partitionedStep(Step workerStep) {
return new StepBuilder("partitionedStep", jobRepository)
.partitioner("workerStep", new ColumnRangePartitioner()) // ID 범위 분할
.step(workerStep)
.gridSize(10) // 10개 파티션으로 분할
.taskExecutor(new SimpleAsyncTaskExecutor())
.build();
}
전략특징사용 시나리오
Multi-threaded Step청크 단위 병렬 처리단일 데이터 소스, 빠른 구현
Parallel Steps독립 Step의 동시 실행이메일+SMS처럼 독립 작업
Partitioning데이터 범위 분할 후 병렬수억 건의 대용량 데이터
Advertisement