6. Checkpointer 패턴
Pattern Overview
- job의 처리 진행 상황(오프셋, 상태)을 잡 외부의 영속 저장소에 주기적으로 기록
- 장애 복구 시 마지막 체크포인트부터 재개
두 가지 체크포인트 주체
프레임워크 기반: Spark Structured Streaming, Flink이 체크포인트 위치만 설정하면 자동 관리합니다.
데이터 스토어 기반: Kafka SDK의 commit(), Kinesis Client Library의 DynamoDB 체크포인트처럼 코드에서 직접 확인(commit) 호출이 필요합니다.
두 가지 체크포인트 방식
설정 기반 (자동): 주기나 위치만 설정하면 프레임워크가 알아서 실행. Spark, Flink이 이 방식입니다.
코드 기반 (수동): 레코드를 읽고 처리한 후 개발자가 명시적으로 commit()을 호출합니다. Kafka consumer SDK가 이 방식입니다.
구현 예시 1: Spark Structured Streaming
# Spark - checkpointLocation만 설정하면 자동 관리write_query = ( input_stream_data .writeStream .outputMode('append') .option('checkpointLocation', f'{base_dir}/checkpoint') .foreachBatch(synchronize_visits_to_files) .start())Spark는 매 microbatch마다 체크포인트를 기록함
$ cat /tmp/dedp/ch03/fault-tolerance/micro-batch/checkpoint/offsets/0# 파티션별 처리 완료 오프셋{"visits":{"1":1276,"0":1224}}microbatch 단위로 기록하므로 오버헤드가 있지만, 재시작 시 중복 처리 범위가 최소화
구현 예시 2: Apache Flink
# Flink - 시간 기반 체크포인트 (30초마다)checkpoint_interval_30_sec = 30000env.enable_checkpointing(checkpoint_interval_30_sec)
env.get_checkpoint_config().enable_externalized_checkpoints( ExternalizedCheckpointCleanup.RETAIN_ON_CANCELLATION)checkpoint_interval_30_sec: 30초마다 체크포인트 생성. Spark(매 microbatch)과 달리 시간 기반.
RETAIN_ON_CANCELLATION: 잡이 실패/취소되어도 체크포인트 파일을 보존. 기본값은 잡 재시작 시 삭제.
EXACTLY_ONCE 모드: stateful 연산(윈도우 카운터 등)에서 각 레코드가 상태에 한 번만 반영되도록 보장.
Delivery Mode와 체크포인트 타이밍
At-least-once: 데이터 처리(쓰기) 후 체크포인트. 장애 시 체크포인트 이후~장애 시점의 레코드를 다시 처리하므로 중복 발생 가능.
읽기 → 처리 → 쓰기 → 체크포인트 ↑ 여기서 죽으면 → 재시작 시 "쓰기"부터 다시 → 중복At-most-once: 데이터 처리 전 체크포인트. 장애 시 체크포인트 이후~장애 시점의 레코드가 유실.
읽기 → 체크포인트 → 처리 → 쓰기 ↑ 여기서 죽으면 → 재시작 시 다음 레코드부터 → 유실Exactly-once: 체크포인트만으로는 달성 불가. 별도의 idempotency 패턴이 필요
주요 Consequences
체크포인트 빈도 vs 레이턴시 trade-off: 자주 찍을수록 → 재시작 시 재처리량이 적지만 → 매번 영속 저장소에 쓰는 오버헤드로 처리 레이턴시 증가. 드물게 찍을수록 → 빠르지만 → 장애 시 재처리 범위가 넓어짐. Exactly-once는 착각: 체크포인트는 exactly-once “느낌”을 주지만, 분산 환경에서 병렬 태스크 중 일부만 실패하면 성공한 태스크의 결과는 이미 쓰여진 상태. 재시작 시 해당 레코드가 중복 처리됨 State 크기와 복구 시간: stateful 잡(세션, 윈도우 카운터)에서는 오프셋뿐 아니라 state 전체를 체크포인트에 포함해야함. state가 클 경우 체크포인트 생성과 복구 모두 느려짐
Concept
- Checkpointer : 스트리밍 잡의 처리 진행 상황(오프셋 + 상태)을 외부 영속 저장소에 주기적으로 기록하는 장애 복구 패턴
- Checkpoint Location : 체크포인트 데이터가 저장되는 외부 저장소 경로. S3, HDFS 등 resilient한 스토리지 사용
- Offset : 데이터 소스(Kafka 등)에서 현재까지 읽은 위치. 체크포인트의 핵심 추적 대상
- At-least-once Delivery : 처리 후 체크포인트. 장애 시 중복 가능하지만 데이터 유실 없음
- At-most-once Delivery : 처리 전 체크포인트. 데이터 유실 가능하지만 중복 없음
- Exactly-once Delivery : 체크포인트만으로 달성 불가. idempotency 패턴과 결합 필요
- RETAIN_ON_CANCELLATION : Flink에서 잡 실패/취소 시 체크포인트를 보존하는 설정. 기본값은 삭제
- Microbatch 체크포인트 (Spark) : 매 microbatch 종료 시 자동으로 오프셋을 기록. 빈도가 높아 재처리 범위 최소화
- 시간 기반 체크포인트 (Flink) : 설정된 간격(예: 30초)마다 체크포인트 생성. 간격 조절로 성능-안정성 trade-off 제어
- Asynchronous Checkpointing : Spark 3.4.0에서 도입된 microbatch와 비동기로 체크포인트를 생성하는 실험적 기능