1. Spring Batch Introduction

엔터프라이즈 도메인 내의 많은 애플리케이션은 미션-크리티컬 환경에서 비즈니스 운영을 수행하기 위해 대량(bulk) 처리가 필요하다. 이러한 비즈니스 운영에는 다음 내용이 포함된다:

  • 사용자 개입 없이 가장 효율적으로 처리되는 대량 정보의, 자동화되고 복잡한 처리. 이러한 작업에는 일반적으로 시간 기반 이벤트(월말 계산, 통지 또는 통신 등)가 포함된다.
  • 매우 큰 데이터(예: 보험 혜택 결정 또는 요율 조정)에서 반복적으로 처리되는 복잡한 비즈니스 규칙의 주기적인 적용.
  • 트랜잭션 방식으로 일반적인 포매팅(formatting), 유효성 검사 및 처리가 필요한 내부 및 외부 시스템에서 수신한 정보를 기록 시스템에 통합한다. 배치 프로세스(Batch processing)는 기업에서 매일 수십억 건의 트랜잭션을 처리하는 데 사용된다.

스프링 배치는 엔터프라이즈 시스템의 일상적인 운영에 필수적인 강력한 배치 애플리케이션을 개발할 수 있도록 설계된 가볍고, 포괄적인 배치 프레임워크이다. 스프링 배치는 사람들이 기대하는 스프링 프레임워크의 특성(생산성, POJO 기반 개발 접근 방식 및 일반적인 사용 편의성)을 기반으로 하며, 개발자가 필요할 때 고급 엔터프라이즈 서비스에 쉽게 접근하고 사용할 수 있도록 한다. 스프링 배치는 스케줄링 프레임워크가 아니다. 상용 및 오픈 소스 영역 모두에서 사용할 수 있는 우수한 엔터프라이즈 스케줄러가 많이 있다. 예를들어 쿼츠(Quartz), 티볼리(Tivoli), 컨트롤엠(Control-M) 등. 스프링 배치는 스케줄러를 대체하는 것이 아니라 스케줄러와 함께 작동하도록 설계되었다.

스프링 배치는 로깅(logging) 및 추적(tracing), 트랜잭션 관리, 잡 프로세싱 통계, 잡 재시작, 스킵(skip), 리소스 관리 등 대용량 레코드 처리에 필요한 필수 기능들을 재사용 가능하도록 제공한다. 또한 최적화 및 파티셔닝 기술을 통해 대량 및 고성능 배치 작업을 가능하게 하는 고급 기술 서비스 및 기능을 제공한다. 간단한 사용 사례(예: 데이터베이스로 파일 읽기 또는 저장 프로시저 실행)와 복잡한, 대량 사용 사례(예: 데이터베이스 간에 대량 데이터 이동, 변환 등) 모두에서 스프링 배치를 사용할 수 있다. 대량 배치 작업은 확장성이 뛰어난 방식으로 프레임워크를 사용하여 대량의 정보를 처리할 수 있다.

1.1. Background

오픈 소스 소프트웨어 프로젝트 및 관련 커뮤니티에서 웹 기반 및 마이크로서비스 기반 아키텍처 프레임워크에 더 많은 관심을 기울이는 동안, 자바 기반 배치 프로세스에 대한 엔터프라이즈 IT 환경의 요구 사항을 수용하기 위해 재사용 가능한 아키텍처 프레임워크에 대한 집중도가 눈에 띄게 부족했다. 재사용 가능한 표준 배치 아키텍처의 부족은, 클라이언트 엔터프라이즈 IT 내에서 개발된 많은 일회성 사내 솔루션을 확산시켰다.

SpringSource(현재 VMware)와 Accenture가 협력하여 이를 바꿨다. 배치 아키텍처 구현에 대한 Accenture의 실무 및 기술 경험, SpringSource의 깊이 있는 기술 경험 및 스프링의 입증된 프로그래밍 모델이 함께 자연스럽고 강력한 파트너십을 형성하여 엔터프라이즈 자바의 중요한 격차를 메우는 것을 목표로 하는 시장 관련 고품질 소프트웨어를 만들었다. 두 회사는 스프링 기반의 배치 아키텍처 솔루션을 개발하여 유사한 문제를 해결하는 여러 고객과 협력했다. 이 협력은 클라이언트가 제기한 실제 문제에 솔루션을 적용할 수 있도록 도움이 되는 몇 가지 유용한 추가 세부 정보와 실제 제약 조건을 제공했다.

Accenture는 지원, 개선 및 기존 기능 세트를 구동하기 위한 커미터 리소스와 독점 배치 처리 아키텍처 프레임워크를 스프링 배치 프로젝트에 기여했다. Accenture의 기여는 몇 세대 동안의 플랫폼들과 배치 아키텍처를 구축한 수십 년간의 경험을 기반으로 한다. (메인프레임의 코볼, 유닉스의 C++, 이제 어디서나 볼 수 있는 자바)

Accenture와 SpringSource의 공동 작업은 소프트웨어 처리 접근 방식, 프레임워크 및 엔터프라이즈 사용자가 배치 애플리케이션을 생성할 때 일관되게 사용할 수 있는 도구의 표준화를 촉진하는 것을 목표로 한다. 기업 IT 환경에 검증된 표준 솔루션을 제공하고자 하는 기업 및 정부 기관은 스프링 배치의 이점을 누릴 수 있다.

1.2. Usage Scenarios

일반적인 배치 프로그램:

  • 데이터베이스, 파일 또는 대기열(queue)에서 많은 수의 레코드를 읽는다.
  • 특정 방식으로 데이터를 처리한다.
  • 수정된 형태로 데이터를 다시 쓴다. 스프링 배치는 이 기본적인 배치의 반복을 자동화하여, 사용자 상호 작용 없이 오프라인 환경에서 유사한 트랜잭션 세트로 처리하는 기능을 제공한다. 배치 작업은 대부분의 IT 프로젝트의 일부이며, 스프링 부트는 강력한 엔터프라이즈급 솔루션을 제공하는, 유일한 오픈 소스 프레임워크이다.

1.2.1. Business Scenarios

스프링 배치는 다음 비즈니스 시나리오를 지원한다:

  • 배치 프로세스를 주기적으로 커밋.
  • 동시(Concurrent) 배치 처리: 잡의 병렬 처리.
  • 단계적, 엔터프라이즈 메시지 기반 처리.
  • 대규모 병렬(parallel) 배치 처리
  • 실패 후 수동 또는 예약된 재시작.
  • 의존 스텝의 순차 처리(워크플로우 기반 배치의 확장)
  • 부분 처리: 레코드 스킵(skip)(예: 롤백)
  • 전체 배치 트랜잭션, 배치 크기가 작거나 존재하는 저장 프로시저 또는 스크립트가 있는 경우

1.2.2. Technical Objectives

스프링 배치의 기술적 목표는 다음과 같다:

  • 배치 개발자가 스프링 프로그래밍 모델을 사용하도록 허용: 비즈니스 로직에 집중하고 프레임워크가 인프라를 관리하도록 한다.
  • 인프라, 배치 실행 환경, 및 배치 애플리케이션 간의 문제를 명확하게 구분한다.
  • 모든 프로젝트에서 구현할 수 있는 인터페이스로 공통의 핵심(core) 실행 서비스를 제공한다.
  • “즉시” 사용할 수 있는 핵심 실행 인터페이스의 간단한 기본 구현체를 제공한다.
  • 모든 계층에서 스프링 프레임워크를 사용하여 서비스를 쉽게 구성, 커스텀 및 확장할 수 있다.
  • 존재하는 모든 핵심 서비스는 인프라 계층에 영향을 주지 않고 쉽게 교체하거나 확장할 수 있어야 한다.
  • 메이븐을 사용하여 구축된, 애플리케이션과 완전히 분리된 아키텍처 JAR로, 간단한 배포 모델을 제공한다.

1.3. Spring Batch Architecture

스프링 배치는 확장성과 다양한 사용자를 고려하여 설계됐다. 다음 이미지는 개발자를 위한 확장성과 사용 편의성을 지원하는 계층화된 아키텍처를 보여준다.

스프링 배치의 아키텍처 계층

Figure 1. 스프링 배치의 아키텍처 계층

이 계층화된 아키텍처는 세 가지 주요 구성 요소를 가지고있다: 애플리케이션(Application), 코어(Core), 그리고 인프라스트럭처(Infrastructure). 애플리케이션에는 스프링 배치를 사용하여 개발자가 작성한 모든 배치 작업 및 커스텀 코드가 포함되어 있다. 배치 코어에는 배치 잡을 시작하고 제어하는 ​​데 필요한 핵심 런타임 클래스가 포함되어 있다. 여기에는 잡런처(JobLauncher), 잡(Job)스텝(Step)에 대한 구현이 포함된다. 인프라스트럭처에는 애플리케이션 개발자(아이템리더(ItemReader)아이템라이터(ItemWriter)와 같은 읽기 및 쓰기)가 모두 사용하는 읽기 및 쓰기 및 핵심 프레임워크 자체(자체 라이브러리인, 재시도(retry)) 서비스(예: RetryTemplate)가 포함되어 있다.

1.3.1. General Batch Principles and Guidelines

배치 솔루션을 구축할 때 다음과 같은 주요 원칙, 가이드라인 및 일반적인 사항을 고려해야 한다.

  • 배치 아키텍처는 일반적으로 온라인 아키텍처에 영향을 미치며 그 반대도 마찬가지다. 빌딩 블록(building block)을 통해 아키텍처와 환경을 모두 염두에 두고 설계한다.
  • 가능한 단순화하고 단일 배치 애플리케이션에서 복잡한 논리 구조를 만들지 말자.
  • 데이터의 처리 및 저장을 물리적으로 가깝게 유지(즉, 처리가 발생하는 곳에 데이터를 유지).
  • 시스템 리소스 사용, 특히 I/O를 최소화한다. 내부 메모리에서 가능한 많은 작업을 수행하자.
  • 애플리케이션 I/O(SQL 문 분석)를 검토하여 불필요한 물리적 I/O를 피하자. 특히 다음 네 가지 일반적인 결함을 찾아야 한다:
    • 데이터를 한 번 읽고 캐시하거나 작업 스토리지에 보관할 수 있는 경우에도 모든 트랜잭션에서 데이터 읽기.
    • 동일한 트랜잭션에서 이전에 읽은 데이터를 다시 읽기.
    • 불필요한 테이블 또는 인덱스 스캔 유발.
    • SQL 문의 WHERE 절에 키 값을 지정하지 않음.
  • 배치 실행에서 잡을 두 번 수행하지 말자. 예를 들어, 보고(report) 목적으로 데이터 요약이 필요한 경우, 데이터가 처음 처리될 때 저장된 합계를 증가시켜야(가능한 경우), 보고용 애플리케이션이 동일한 데이터를 다시 처리하지 않을 수 있다.
  • 처리 중에 시간을 소모하는 재할당을 방지하기 위해 배치 애플리케이션 시작 시 충분한 메모리를 할당해야 한다.
  • 항상 데이터 무결성과 관련하여 최악의 상황을 가정하자. 데이터 무결성을 유지하기 위해 적절한 검사 및 레코드 유효성 검사를 삽입하자.
  • 가능한 경우 내부 유효성 검사를 위한 체크섬(checksum)을 구현하자. 예를 들어, 플랫 파일(flat file)에는 파일의 전체 레코드와 키 필드의 집계를 알려주는 트레일러 레코드(trailer record)가 있어야 한다.
  • 실제 데이터 볼륨이 있는 프로덕션 환경에서 가능한 빨리 스트레스 테스트를 계획하고 실행한다.
  • 대규모 배치 시스템에서, 특히 시스템이 연중무휴(on a 24-7 basis)로 온라인 애플리케이션과 동시에 실행되는 경우 백업이 어려울 수 있다. 데이터베이스 백업은 일반적으로 온라인 설계에서 잘 관리되지만 파일 백업도 마찬가지로 중요하게 고려해야 한다. 시스템이 플랫 파일에 의존하는 경우 파일 백업 절차가 마련되어 문서화되어야 할 뿐만 아니라 정기적으로 테스트되어야 한다.

1.3.2. Batch Processing Strategies

배치 시스템의 설계 및 구현을 돕기 위해, 기본 배치 애플리케이션의 빌딩 블록(building blocks) 및 패턴을 디자이너와 프로그래머에게 샘플 구조 차트 및 코드 셸 형태로 제공해야 한다. 배치 작업 설계를 시작할 때, 비즈니스 로직은 다음 표준 빌딩 블록을 사용하여 구현할 수 있는 일련의 단계로 분해되어야 한다:

  • 변환 애플리케이션(Conversion Applications): 외부 시스템에서 제공하거나 외부 시스템을 위해 생성된 각 유형의 파일에 대해, 변환 애플리케이션을 생성하여 제공된 트랜젝션 레코드를 처리에 필요한 표준 형식으로 변환해야 한다. 이런 유형의 배치 애플리케이션은 부분 또는 전체적으로 번역 유틸리티 모듈로 구성될 수 있다.(기본 배치 서비스 참고).
  • 검증 애플리케이션(Validation Applications): 유효성 검사 애플리케이션은 모든 입력 및 출력 레코드가 정확하고 일관성이 있는지 확인한다. 유효성 검사는 일반적으로 파일 헤더 및 트레일러, 체크섬 및 유효성 검사 알고리즘, 레코드-레벨 교차-검사를 기반으로 한다.
  • 추출 애플리케이션(Extract Applications): 추출 애플리케이션은 데이터베이스 또는 입력 파일에서 레코드 집합을 읽고, 미리 정의된 규칙에 따라 레코드를 선택하고, 레코드를 출력 파일에 쓴다.
  • 추출/변경 애플리케이션(Extract/Update Applications): 추출/변경 애플리케이션은 데이터베이스 또는 입력 파일에서 레코드를 읽고 각 입력 레코드에서 찾은 데이터에 따라, 데이터베이스 또는 출력 파일을 변경한다.
  • 처리 및 변경 애플리케이션(Processing and Updating Applications): 처리 및 변경 애플리케이션은 추출 또는 검증 애플리케이션의 입력 트랜잭션에 대한 처리를 수행한다. 일반적으로 처리에 필요한 데이터를 얻기 위해 데이터베이스를 읽고, 데이터베이스를 변경하고 출력 처리를 위한 레코드를 생성하는 작업이 포함된다.
  • 출력/포맷 애플리케이션(Output/Format Applications): 출력/포맷 애플리케이션은 입력 파일을 읽고, 표준 포맷에 따라 이 레코드에서 데이터를 재구성하고, 프린팅하거나 다른 프로그램 또는 시스템으로 전송하기 위한 출력 파일을 생성한다.

또한, 앞서 언급한 빌딩 블록을 사용하여 구축할 수 없는 비즈니스 로직에 대해 기본 애플리케이션 셸을 제공해야 한다.

메인 빌딩 블록 외에도, 각 애플리케이션은 다음과 같은 하나 이상의 표준 유틸리티를 사용할 수 있다:

  • 정렬(Sort): 입력 파일을 읽고 레코드의 정렬 키 필드에 따라 레코드가 다시 정렬된 출력 파일을 생성하는 프로그램이다. 정렬은 일반적으로 표준 시스템 유틸리티에 의해 수행된다.
  • 분할(Split): 단일 입력 파일을 읽고 필드 값을 기반으로 여러 출력 파일 중 하나에 각 레코드를 쓰는 프로그램이다. 분할은 매개변수-기반 표준 시스템 유틸리티에 의해 조정되거나 수행될 수 있다.
  • 병합(Merge): 여러 입력 파일에서 레코드를 읽고 입력 파일에서 결합된 데이터로 하나의 출력 파일을 생성하는 프로그램이다. 병합은 매개변수-기반 표준 시스템 유틸리티로 조정하거나 수행할 수 있다.

배치 애플리케이션은 입력 소스별로 추가로 분류할 수 있다:

  • 데이터베이스 기반 애플리케이션은 데이터베이스에서 검색된 행 또는 값에 의해 구동된다.
  • 파일 기반 애플리케이션은 파일에서 검색된 레코드 또는 값에 의해 구동된다.
  • 메시지 기반 애플리케이션은 메시지 큐에서 검색된 메시지에 의해 구동된다.

모든 배치 시스템의 기초는 처리 전략이다. 전략 선택에 영향을 미치는 요인에는 다음 내용이 있다: 예상 배치 시스템 볼륨, 온라인 시스템 또는 다른 배치 시스템과의 동시성, 사용 가능한 배치 윈도우. (더 많은 기업이 연중무휴(24x7) 가동을 원하면서 명확한 배치 윈도우가 사라지고 있다.)

배치에 대한 일반적인 처리 옵션은 구현 복잡성이 증가하는 순서대로 다음과 같다:

  • 오프라인 모드에서 배치 윈도우의 정상적인 처리.
  • 동시(Concurrent) 배치 또는 온라인 처리
  • 동시에 많은 배치 실행 또는 작업의 병렬(Parallel) 처리.
  • 파티셔닝(같은 작업의 여러 인스턴스를 동시에 처리).
  • 위 옵션의 조합

이러한 옵션의 일부 또는 전부 상용 스케줄러에서 지원한다.

이 절의 나머지 부분에서는 이러한 처리 옵션에 대해 자세히 설명한다. 일반적으로, 배치 프로세스에서 채택하는 커밋 및 잠금 전략은 수행되는 처리 유형에 따라 다르며 온라인 잠금 전략도, 동일한 원칙을 사용해야 한다. 따라서, 배치 아키텍처는 전체 아키텍처를 설계할 때 나중에 미뤄 생각할 수 없다.

잠금 전략은 일반 데이터베이스 잠금만 사용하거나 아키텍처에서 추가 사용자 지정 잠금 서비스를 구현하는 것일 수 있다. 잠금 서비스는 데이터베이스 잠금(예: 필요한 정보를 전용 데이터베이스 테이블에 저장)을 추적하고 데이터베이스 작업을 요청하는 애플리케이션에 권한을 부여하거나 거부한다. 잠금 상황의 경우 배치 작업 중단을 방지하기 위해 이 아키텍처에서 재시도(retry) 로직를 구현할 수도 있다.

  1. 배치 윈도우에서 일반 처리 온라인 사용자나 다른 배치 프로세스가 업데이트 중인 데이터를 필요로 하지 않는 분리된 배치 윈도우에서 실행되는 단순 배치 프로세스의 경우 동시성은 문제가 되지 않으며 배치 종료 시 단일 커밋을 수행할 수 있다. 대부분의 경우, 더욱 강력한 접근 방식이 필요하다. 배치 시스템은 복잡도와 처리하는 데이터 양 측면에서, 시간이 지남에 따라 증가하는 경향이 있음을 명심하자. 잠금 전략이 없고 시스템이 여전히 단일 커밋 지점에 의존하는 경우, 배치 프로그램을 수정하는 것이 어려울 수 있다. 따라서, 가장 단순한 배치 시스템을 사용하더라도, 재시작 복구 옵션에 대한 커밋 로직의 필요성과 이 절의 뒷부분에서 설명하는 더 복잡한 사례에 관한 정보를 고려해야 한다.

  2. 동시 배치 또는 온라인 처리 온라인 사용자가 동시에 업데이트할 수 있는 데이터를 처리하는 배치 애플리케이션은 온라인 사용자가 필요로 할 수 있는 데이터(데이터베이스 또는 파일)를 몇 초 이상 잠그지 않아야 한다. 또한, 몇 번의 트랜잭션이 끝날 때마다 데이터베이스에 업데이트를 커밋해야 한다. 이렇게 하면 다른 프로세스에서 사용할 수 없는 데이터 부분과 데이터를 사용할 수 없는 경과 시간이 최소화된다. 물리적 잠금을 최소화하는 또 다른 옵션은 낙관적 잠금 패턴 또는 비관적 잠금 패턴을 사용하여 논리적 로우 레벨(row-level)의 잠금을 구현하는 것이다.

    • 낙관적 잠금(Optimistic locking)은 레코드 경합(contention) 가능성이 낮다고 가정한다. 일반적으로 배치 및 온라인 처리에서 동시에 사용되는 각 데이터베이스 테이블에 타임스탬프 컬럼을 삽입하는 것을 의미한다. 애플리케이션이 처리를 위해 로우을 가져올 때 타임스탬프도 가져온다. 그런 다음 애플리케이션이 처리된 로우를 업데이트하려고 시도하면, update는 WHERE 절의 기존 타임스탬프를 사용한다. 타임스탬프가 일치하면, 데이터와 타임스탬프가 업데이트된다. 타임스탬프가 일치하지 않으면, 다른 애플리케이션이 가져오기와 업데이트 시도 사이에 동일한 로우을 업데이트했음을 나타낸다. 따라서 업데이트를 수행되지 않는다.
    • 비관적 잠금(Pessimistic locking)은 레코드 경합 가능성이 높다고 가정하는 잠금 전략이므로, 검색 시 물리적 또는 논리적 잠금을 얻어야 한다. 비관적인 논리적 잠금의 한 유형은 데이터베이스 테이블에서 전용 잠금 컬럼(lock-column)을 사용하는 것이다. 애플리케이션이 업데이트할 로우을 검색하면 잠금 컬럼에 플래그를 설정한다. 플래그가 있으면 동일한 로우을 검색하려는 다른 애플리케이션이 논리적으로 실패한다. 플래그를 설정하는 애플리케이션이 로우을 업데이트하면, 플래그도 지워지므로 다른 애플리케이션에서 해당 로우을 검색할 수 있다. 데이터의 무결성은 초기 가져오기와 플래그 설정 사이에서도 유지되어야 한다. - 예를 들어, 데이터베이스 잠금(예: SELECT FOR UPDATE)을 사용. 또한 이 방법은 레코드가 잠겨 있는 동안 사용자가 실행하는 경우 잠금을 해제하는 시간-제한 메커니즘을 구축하는 것이 다소 쉽다는 점을 제외하면 물리적 잠금과 동일한 단점이 있다.

이러한 패턴은 배치 처리에 반드시 적합하지는 않지만, 동시 배치(concurrent batch) 및 온라인 처리(예로 데이터베이스가 로우 레벨 잠금을 지원하지 않는 경우)에 사용될 수 있다. 일반적으로, 낙관적 잠금은 온라인 애플리케이션에 더 적합하고 비관적 잠금은 배치 애플리케이션에 더 적합하다. 논리적 잠금이 사용될 때마다, 논리적 잠금으로 보호되는 데이터 엔터티에 접근하는 모든 애플리케이션에 대해 동일한 체계를 사용해야 한다.

이 두 솔루션 모두 단일 레코드 잠금만 처리한다. 종종, 논리적으로 관련된 레코드 그룹을 잠가야 할 수도 있다. 물리적 잠금을 사용하면 잠재적인 교착상태(deadlocks)를 피하기 위해 매우 신중하게 관리해야 한다. 논리적 잠금을 사용하면, 일반적으로 보호하려는 논리적 레코드 그룹을 이해하고 잠금이 일관되고 교착상태가 아님을 보장할 수 있는 논리적 잠금 매니저를 구축하는 것이 가장 좋다. 이 논리적 잠금 관리자는 일반적으로 잠금 관리, 경합 보고, 시간 초과 메커니즘 및 기타 문제를 위해 자체 테이블을 사용한다.

  1. 병렬 처리 병렬 처리를 사용하면 여러 배치 실행 또는 잡을 병렬로 실행하여 총 경과된 배치 처리 시간을 최소화할 수 있다. 잡이 동일한 파일, 데이터베이스 테이블 또는 인덱스 공간을 공유하지 않는다면 문제가 되지 않는다. 또 다른 옵션은 제어 테이블을 사용하여 상호 의존성을 유지하기 위한 아키텍처 모듈을 구축하는 것이다. 제어 테이블에는 각 공유 리소스에 대한 로우과 애플리케이션에서 사용 중인지 여부가 포함되어야 한다. 병렬 작업 배치 아키텍처 또는 애플리케이션은 해당 테이블에서 정보를 검색하여 필요한 리소스에 대한 접근 권한을 얻을 수 있는지 여부를 결정한다. 데이터 접근이 문제가 되지 않는 경우, 추가 쓰레드를 사용해 병렬 처리를 구현할 수 있다. 메인프레임 환경에서, 모든 프로세스에 적절한 CPU 시간을 보장하기 위해, 병렬 잡 클래스가 사용됐다. 그럼에도 불구하고, 솔루션은 실행 중인 모든 프로세스에 대한 타임 슬라이스를 보장할 수 있을 만큼 충분히 견고해야 한다. 병렬 처리의 다른 주요 문제에는 로드 밸런싱과 파일, 데이터베이스 버퍼 풀 등과 같은 일반 시스템 리소스의 가용성이 포함된다. 또한 제어 테이블 자체가 중요한 리소스가 되기 쉽다.

  2. 파티셔닝 파티셔닝을 사용하면 여러 버전의 대규모 배치 애플리케이션을 동시에 실행할 수 있다. 이것의 목적은 긴 배치 작업을 처리하는 데 필요한 경과 시간을 줄이는 것이다. 성공적으로 분할할 수 있는 프로세스는 입력 파일을 분할하거나 기본 데이터베이스 테이블을 분할하여 애플리케이션이 다른 데이터 세트에 대해 실행될 수 있는 프로세스이다.

또한, 분할된 프로세스는 할당된 데이터 세트만 처리하도록 설계되어야 한다. 파티셔닝 아키텍처는 데이터베이스 설계 및 데이터베이스 파티셔닝 전략과 밀접하게 연결되어야 한다. 데이터베이스 파티셔닝이 반드시 데이터베이스의 물리적 파티셔닝(대부분의 경우, 권장됨)을 의미하는 것은 아니다. 다음 이미지는 파티셔닝 방식을 보여준다:

Partitioned Process

이미지 2. 파티셔닝 프로세스

아키텍처는 파티션 수를 동적으로 구성할 수 있을 만큼 충분히 유연해야 한다. 자동 및 커스텀 구성을 모두 고려해야 한다. 자동 구성은 입력 파일 크기 및 입력 레코드 수와 같은 파라미터를 기반으로 할 수 있다.

4.1 파티셔닝 접근법
파티셔닝 방식을 선택하는 것은 사례별로 이루어져야 한다. 다음 목록은 가능한 파티셔닝 접근 방식 중 일부를 설명한다:

(1) 레코드 세트의 고정 및 균등 분해
입력 레코드 세트를 균등 분해(예: 각 부분이 전체 레코드 세트의 정확히 1/10을 갖는도록 함)하는 작업이 포함된다. 그런 다음 배치/추출 애플리케이션의 한 인스턴스에서 각 부분을 처리한다.

이 접근 방법을 사용하려면, 레코드 설정을 분할하기 위한 전처리가 필요하다. 이 분할의 결과는 배치/추출 애플리케이션에 대한 입력으로 사용할 수 있는 하한 및 상한 배치 번호이며, 해당 부분으로 처리를 제한할 수 있다.

전처리는 레코드 집합의 각 부분의 경계를 계산하고 결정해야 하므로 큰 오버헤드가 될 수 있다.

(2) 키 컬럼(column)으로 나누기
여기서는 위치 코드와 같은 키 열로 설정된 입력 레코드를 분할하고, 각 키의 데이터를 배치 인스턴스에 할당하는 작업이 포함된다. 이를 달성하기 위해, 열 값은 다음 중 하나일 수 있다:

  • 파티셔닝 테이블(이 섹션의 뒷부분에서 설명함)로 배치 인스턴스에 할당한다.
  • 값의 일부(예: 0000-0999, 1000-1999 등)로 배치 인스턴스에 할당한다.

옵션 1에서, 새 값을 추가한다는 것은 새 값이 특정 인스턴스에 추가되도록 배치 또는 추출을 수동으로 재구성하는 것을 의미한다.

옵션 2에서, 모든 값이 배치 잡 인스턴스에 포함되도록 한다. 그러나, 하나의 인스턴스에서 처리되는 값의 수는 로우 값의 분포(0000-0999 범위에 위치가 많고 1000-1999 범위에 위치가 적을 수 있음)에 따라 다르다. 이 옵션에서는, 분할을 염두에 두고 데이터 범위를 설계해야 한다.

두 옵션 모두 배치 인스턴스에 대한 레코드의 최적 균등 분포를 실현할 수 없다. 사용되는 배치 인스턴스 수에 대한 동적 구성이 없다.

(3) 뷰 분리
이 접근 방식은 기본적으로 데이터베이스 레벨에서 키 컬럼으로 구분된다. 레코드 세트를 뷰로 분리하는 작업이 포함된다. 이러한 뷰는 처리 중에 배치 애플리케이션의 각 인스턴스에서 사용된다. 분리는 데이터를 그룹화하여 수행된다.

이 옵션을 사용하면, 배치 애플리케이션의 각 인스턴스가 특정 뷰(메인 테이블 대신)에 도달하도록 구성되어야 한다. 또한, 새 데이터 값을 추가하면, 이 새 데이터 그룹이 뷰에 포함되어야 한다. 인스턴스 수를 변경하면, 뷰가 변경되므로 동적 구성 기능이 없다.

(4) 처리 표시기 추가
여기에는 표시기 역할을 하는, 입력 테이블에 새 컬럼을 추가하는 작업이 포함된다. 처리 전 단계로, 모든 지표를 미처리로 표시한다. 배치 애플리케이션의 레코드 가져오기 단계 중, 개별 레코드가 처리되지 않은 것으로 표시된 상태에서 레코드를 읽고, 읽은 후에는(잠금 상태로) 처리 중으로 표시한다. 해당 레코드가 완료되면, 표시기가 완료 또는 오류로 업데이트된다. 추가 컬럼을 통해 레코드가 한 번만 처리되도록 보장하므로, 변경 없이 배치 애플리케이션의 많은 인스턴스를 시작할 수 있다.

이 옵션을 사용하면, 테이블의 I/O가 동적으로 증가한다. 업데이트 배치 애플리케이션의 경우, 쓰기가 발생해야 하므로, 이러한 영향이 줄어든다.

(5) 플랫 파일로 테이블 추출
이 접근 방식은 테이블을 플랫 파일로 추출하는 것을 포함한다. 그런 다음 이 파일을 여러 세그먼트로 분할하고 배치 인스턴스에 대한 입력으로 사용할 수 있다. 이 옵션을 사용하면, 테이블을 파일로 추출하고 분할하는 추가 오버헤드로 인해 다중 분할 효과가 없어질 수 있다. 파일 분할 스크립트를 변경하여 동적으로 구성이 가능하다.

(6) 해싱 컬럼 사용
이 체계는 드라이브 레코드(driver record)를 검색하는 데 사용되는 데이터베이스 테이블에 해시 컬럼(키 또는 인덱스)을 추가하는 작업이 포함된다. 해시 컬럼에는 특정 로우을 처리하는 배치 애플리케이션의 인스턴스를 결정하는 표시기가 있다. 예를 들어 시작할 배치 인스턴스가 세 개 있는 경우 ‘A’ 표시기는 인스턴스 1에서 처리할 로우을 표시하고 ‘B’ 표시기는 인스턴스 2에서 처리할 로우을 표시하고 ‘C’ 표시기는 인스턴스 3에서 처리할 로우을 표시한다.

레코드를 검색하는 데 사용되는 절차에는 특정 표시기의 모든 로우을 선택하는 추가 WHERE 절이 있다. 이 테이블의 삽입에는 인스턴스 중 하나(예: ‘A’)로, 기본 설정되는 마커 필드의 추가가 포함된다.

서로 다른 인스턴스 간 로드를 재분배하는 것과 같이, 지표를 업데이트하는 데 간단한 배치 애플리케이션이 사용된다. 충분히 많은 수의 새 로우가 추가되면, 이 배치 처리를 실행하여(배치 윈도우를 제외하고, 언제든지) 새 로우을 다른 인스턴스에 재배포할 수 있다.

배치 애플리케이션의 추가 인스턴스는 새로운 수의 인스턴스와 함께 작동하도록 표시기를 재배포하기 위해 배치 애플리케이션을 실행(이전 단락에서 설명한 대로)하기만 하면 된다.

4.2 데이터베이스 및 애플리케이션 설계 원칙
파티션 데이터베이스 테이블에 대해 실행되고 키 컬럼 접근 방식을 사용하는 다중 파티션 애플리케이션을 지원하는 아키텍처에는 파티션 파라미터를 저장하기 위한 중앙 파티션 리포지터리가 포함되어야 한다. 이것은 유연성을 제공하고 유지 보수성을 보장한다. 리포지터리는 일반적으로 파티션 테이블로 알려진, 단일 테이블로 구성된다.

파티션 테이블에 저장된 정보는 정적(static)이며, 일반적으로, DBA가 관리해야 한다. 테이블은 다중 파티션 애플리케이션의 각 파티션에 대한 정보의 한 로우으로 구성되어야 한다. 테이블에는 프로그램 ID 코드, 파티션 번호(파티션의 논리적 ID), 이 파티션에 대한 데이터베이스 키 컬럼의 낮은 값 및 이 파티션에 대한 데이터베이스 키 컬럼의 높은 값에 대한 컬럼이 있어야 한다.

프로그램 시작 시 프로그램 id 및 파티션 번호는 아키텍처(특히 제어 처리 tasklet)에서 애플리케이션으로 전달되어야 한다. 키 컬럼 접근 방식을 사용하는 경우, 이러한 변수는 애플리케이션이 처리할 데이터 범위를 결정하기 위해 파티션 테이블을 읽는 데 사용된다. 또한, 파티션 번호는 처리 전반에 걸쳐 사용되어야 한다:

  • 병합 프로세스가 제대로 작동하려면, 출력 파일 또는 데이터베이스 업데이트에 추가해야 한다.
  • 일반 처리는 배치 로그에 보고하고 오류는 아키텍처 오류 처리기에 보고한다.

4.3 교착상태 최소화
애플리케이션이 병렬로 실행되거나 파티션된 경우, 데이터베이스 리소스에 대한 경합(contention) 및 교착 상태(deadlocks)가 발생할 수 있다. 데이터베이스 설계 시, 가능한 한 잠재적 경합 상황을 제거하는 것이 중요하다.

또한, 개발자는 데이터베이스 인덱스 테이블이 교착 상태 방지 및 성능을 염두에 두고 설계되었는지 확인해야 한다.

교착 상태 또는 핫스팟은 로그 테이블, 제어 테이블 및 잠금 테이블과 같은 관리 또는 아키텍처 테이블에서 자주 발생한다. 이러한 영향도 고려해야 한다. 현실적인 스트레스 테스트는 아키텍처에서 가능한 병목현상(bottlenecks)을 식별하는 데 중요하다.

데이터 충돌의 영향을 최소화하기 위해, 아키텍처는 데이터베이스에 연결할 때 또는 교착상태가 발생할 때 서비스(예: 대기 및 재시도 간격)를 제공해야 한다. 특정 데이터베이스 반환 코드에 반응하는 기본 제공 메커니즘을 의미하며, 즉각적인 오류를 발생시키는 대신, 미리 결정된 시간 동안 기다렸다가 데이터베이스 작업을 다시 시도한다.

4.4 파라미터 전달 및 유효성 검사
파티션 아키텍처는 애플리케이션 개발자에게 상대적으로 투명해야 한다. 아키텍처는 다음을 포함하여 파티션 모드에서 애플리케이션 실행과 관련된 모든 작업을 수행해야 한다:

  • 애플리케이션 시작 전에 파티션 파라미터 검색.
  • 애플리케이션 시작 전에 파티션 파라미터 유효성 검사.
  • 시작 시 애플리케이션에 파라미터 전달.

유효성 검사에는 다음을 확인하는 검사가 포함되어야 한다:

  • 애플리케이션에 전체 데이터 범위를 포괄할 수 있는 충분한 파티션이 있다.
  • 파티션 사이에 간격이 없다.

데이터베이스가 파티션된 경우, 단일 파티션이 데이터베이스 파티션에 걸쳐 있지 않도록 하기 위해 일부 추가 유효성 검사가 필요할 수 있다.

또한, 아키텍처는 파티션의 통합을 고려해야 한다. 주요 질문은 다음과 같다.

  • 다음 작업 단계로 이동하기 전에 모든 파티션을 완료해야 하나?
  • 파티션 중 하나가 중단되면 어떻게 되나?

이 장은 스프링 배치 5의 주요 하이라이트를 보여준다. 자세한 내용은 마이그레이션 가이드를 참고하자.