본문 바로가기
Java & Kotlin/Spring Batch

[SpringBatch] 멀티쓰레드 Step

by heekng 2022. 7. 2.
반응형

멀티쓰레드 Step

TOCHE 프로젝트를 진행하면서 대용량 배치 처리를 해야하는 일이 생겼다.
기존의 배치는 chunk 기반의 단순한 배치이다.

private Step useDeckStatsStep() {
    return stepBuilderFactory.get("useDeckStatsStep")
            .<MatchInfo, MatchInfo>chunk(chunkSize)
            .reader(useDeckStatsReader())
            .processor(useDeckStatsProcessor)
            .writer(useDeckStatsWriter())
            .build();
}

위와 같은 Step을 10개의 쓰레드를 이용해 멀티쓰레드 환경으로 실행해야 했다.

private final int poolSize = 10;

...

private Step useDeckStatsStep() {
    return stepBuilderFactory.get("useDeckStatsStep")
            .<MatchInfo, MatchInfo>chunk(chunkSize)
            .reader(useDeckStatsReader())
            .processor(useDeckStatsProcessor)
            .writer(useDeckStatsWriter())
            .taskExecutor(executor())
            .throttleLimit(poolSize)
            .build();
}

...

private TaskExecutor executor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(poolSize);
    executor.setMaxPoolSize(poolSize);
    executor.setThreadNamePrefix("multi-thread-");
    executor.setWaitForTasksToCompleteOnShutdown(Boolean.TRUE);
    executor.initialize();
    return executor;
}

...
  • ThreadPoolTaskExecutor: 쓰레드 풀을 이용해 쓰레드를 관리하는 방식
    • corePoolSize: Pool의 기본 사이즈
    • maxPoolSize: Pool의 최대 사이즈
    • threadNamePrefix: 쓰레드 앞에 붙을 이름
  • throttleLimit: 생성된 쓰레드 중 작업에 사용할 쓰레드 수를 설정한다.

위와 같이 taskExecutorthrottleLimit을 사용해 멀티쓰레드 환경을 설정한다.

주의할 점은 ItemReader의 Thread Safe 유무이다.

private ItemReader<MatchInfo> useDeckStatsReader() {
    return new JpaPagingItemReaderBuilder<MatchInfo>()
            .name("useDeckStatsReader")
            .entityManagerFactory(emf)
            .pageSize(chunkSize)
            .queryString("select m from MatchInfo m where m.isDeckCollected = FALSE")
            .saveState(false)
            .build();
}

나의 경우 JpaPagingItemReader을 사용했는데

JpaPagingItemReadersaveStatefalse로 설정했을 경우 thread-safe를 지원한다고 설명되어있다.
그러므로 saveState를 false로 설정한다면 모든 설정이 완료된다.

하지만 사용을 못했다…

내가 사용하던 processor에는 JPA를 이용해 데이터를 입력 또는 조회하는 단계가 포함되어있다.
그래서 서로 다른 쓰레드가 같은 테이블을 조회하는 과정에서 문제가 발생했다…
기존의 배치 구조가 멀티쓰레드 환경에서는 당연히 나타날 수 밖에 없는 문제이기 때문에, 단일 쓰레드 방식으로 사용하도록 되돌렸다.
앞으로의 배치에서 같은 문제를 겪을 수 있기에 주의해서 배치를 구성해야겠다.

반응형