티스토리 뷰

728x90

 

 

요약

Kafka 컨슈머의 오프셋(commit) 전략은 “메시지를 정확히 한 번 처리할 수 있느냐, 아니면 중복·유실을 감수하느냐”를 결정합니다.
편리한 자동 커밋(enable.auto.commit=true)은 주기적 타이머로 오프셋을 저장하지만, 장애 시 이미 받은 레코드가 아직 커밋되지 않은 상태로 재처리·유실 위험이 큽니다. 
따라서 실전 서비스에서는 수동 커밋 API(commitSync, commitAsync)로 “업무 로직 완료 ↔ 오프셋 저장” 을 직접 묶어야 합니다. 
commitSync() 는 브로커 ACK를 받을 때까지 블로킹 → 안정성 최우선, 반면 commitAsync() 는 논블로킹·콜백 기반으로 처리량을 높이되 실패 재시도는 개발자가 책임져야 합니다. 
많은 팀이 “루프 내 commitAsync + 종료 직전 commitSync” 패턴으로 속도와 안정성을 절충합니다. 
아래에서는 자동 커밋의 한계, 수동 커밋 두 방식의 차이, 예외 처리·트랜잭션 연계 팁, Java/Python 예제를 단계별로 정리합니다.


1. 자동 커밋의 편리함과 함정

1.1 자동 커밋이란?

  • 클라이언트는 auto.commit.interval.ms(기본 5 초)마다 현재 오프셋을 __consumer_offsets 토픽에 백그라운드로 기록합니다. 
  • 설정 한 줄로 끝나 개발 초기·단순 로그 수집에 자주 쓰입니다.

1.2 문제점

위험 설명

중복 처리 컨슈머가 배치 로직을 끝내기 전 장애 → 마지막 커밋 이후 레코드를 다시 읽음
데이터 유실 at-most-once 패턴(수신 즉시 커밋)으로 바꾸면 장애 시 처리 전 레코드가 영영 손실.
제3시스템 일관성 DB 트랜잭션과 오프셋 저장 시점을 분리할 길이 없어 이중 커밋 문제 발생. 

2. 수동 커밋이 필요한 이유

2.1 commitSync() — 안정성 최우선

  • 메서드가 블로킹되어 브로커 ACK를 확실히 받은 뒤 반환 → 커밋 실패 시 예외를 직접 처리.
  • 자동으로 재시도(네트워크 오류 등)하므로 개발자가 추가 루프를 돌릴 필요가 없습니다.
  • 단점은 RTT 만큼 지연이 늘어 TPS가 10~30 % 줄 수 있다는 보고. 

2.2 commitAsync() — 처리량·지연 최적화

  • 요청을 비동기 전송 후 바로 다음 폴링으로 넘어가 처리 속도를 극대화합니다.
  • 브로커 실패 ↔ 네트워크 장애 시 재시도하지 않으므로 콜백에서 오류를 받아 직접 대응해야 안정성이 확보됩니다. 

2.3 하이브리드 전략

  • “루프마다 commitAsync() → 종료·리밸런스 직전 commitSync()” 패턴이 Confluent 가이드의 추천안입니다. 
  • 이렇게 하면 평상시엔 낮은 지연높은 처리량, 종료 경계에서는 정확성을 동시에 충족합니다. 

3. 예제 코드

3.1 Java (수동 커밋 샘플)

Properties p = new Properties();
p.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
p.put(ConsumerConfig.GROUP_ID_CONFIG, "safe-demo");
p.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, "false");           // 자동 커밋 OFF
p.put(ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG,
      "org.apache.kafka.common.serialization.StringDeserializer");
p.put(ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG,
      "org.apache.kafka.common.serialization.StringDeserializer");

try (KafkaConsumer<String,String> c = new KafkaConsumer<>(p)) {
    c.subscribe(List.of("orders"));
    while (running) {
        ConsumerRecords<String,String> recs = c.poll(Duration.ofMillis(500));
        for (ConsumerRecord<String,String> r : recs) {
            process(r);          // 업무 로직
        }
        c.commitAsync((offsets, ex) -> {     // 빠른 루프
            if (ex != null) log.error("async commit fail", ex);
        });
    }
    // 정상 종료 시 마지막 배치 보증
    c.commitSync();
}
  • 예제는 async + final sync 패턴을 구현하여 성능과 안전성을 모두 확보합니다.

3.2 Python (kafka-python)

from kafka import KafkaConsumer, TopicPartition, OffsetAndMetadata

consumer = KafkaConsumer(
    'orders',
    bootstrap_servers='localhost:9092',
    group_id='safe-demo',
    enable_auto_commit=False,
    auto_offset_reset='earliest'
)

try:
    for msg in consumer:
        process(msg.value)
        # 파티션별 오프셋 객체 생성
        tp = TopicPartition(msg.topic, msg.partition)
        offsets = {tp: OffsetAndMetadata(msg.offset+1, None)}
        consumer.commit_async(offsets=offsets)
except Exception as e:
    print("error", e)
finally:
    consumer.commit()   # 종료 보증
    consumer.close()
  • commit_async() 는 프로미스가 없어 예외 로깅만 가능, 재시도는 직접 구현해야 함을 강조합니다.

4. 실전 전략 & 모범 사례

4.1 트랜잭션/외부 DB와 일관성 맞추기

  • “DB 커밋 ➜ Kafka 오프셋 커밋” 순서로 2-Phase 느낌의 애플리케이션 가상 트랜잭션을 구성하라.
  • 확실한 Exactly-Once 가 필요하면 Kafka 트랜잭션 API + 멱등 프로듀서 로 전환.

4.2 예외·리밸런스 대비 콜백 처리

  • commitAsync(callback) 에서 실패 오프셋을 로그 + 재시도 큐 로 남겨 다음 폴링에서 commitSync() 로 복구한다. 
  • 리밸런스 리스너(ConsumerRebalanceListener)에서 파티션 회수 전 commitSync() 호출해 중복 소비 가능성을 최소화. 

4.3 모니터링 지표

메트릭 역할

records-lag 배치 지연이 커지면 커밋 주기·처리 속도 점검
commit-latency-avg/max 브로커 ACK 지연 관찰 → 네트워크·I/O 병목 파악
commit-failure-rate Async 오류 빈도 모니터링, 알람 설계 

5. 결론

  • 자동 커밋은 개발 초기·손실 허용 시나리오에만 쓰고,
    비즈니스 데이터에는 반드시 enable.auto.commit=false + 수동 커밋을 적용하세요. 
  • commitAsync() + (종료 or 리밸런스) commitSync() 패턴이 가장 널리 검증된 절충안입니다.
  • 외부 DB·캐시와 “같이 커밋”해야 한다면 오프셋 저장 타이밍을 업무 트랜잭션과 동일 영역에 배치하여 정확성을 확보하십시오. 

안전한 오프셋 관리는 카프카 파이프라인의 데이터 정합성과 장애 복원력을 결정합니다. 위 전략을 바탕으로 서비스 특성에 맞는 커밋 정책을 설계해 보세요. 

 

 

728x90
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/07   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함