1149 words
6 minutes
[DE Design Pattern]03-06. Static, Dynamic Late Data Integrator

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마다 체크포인트를 기록함

Terminal window
$ cat /tmp/dedp/ch03/fault-tolerance/micro-batch/checkpoint/offsets/0
# 파티션별 처리 완료 오프셋
{"visits":{"1":1276,"0":1224}}

microbatch 단위로 기록하므로 오버헤드가 있지만, 재시작 시 중복 처리 범위가 최소화

# Flink - 시간 기반 체크포인트 (30초마다)
checkpoint_interval_30_sec = 30000
env.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와 비동기로 체크포인트를 생성하는 실험적 기능

[DE Design Pattern]03-06. Static, Dynamic Late Data Integrator
https://yjinheon.netlify.app/posts/02de/de-design-pattern/03-dead-letter/03-dl-06-checkpointer/
Author
Datamind
Published at
2025-02-27
License
CC BY-NC-SA 4.0