Kafka 생산자 및 소비자 오류 복구 메커니즘

생산자 측면 재시도 구현

메시지 전송 실패 시 복구를 위해 생산자 구성에서 재시도 매개변수를 설정합니다. 비동기 전송과 콜백 핸들러를 활용하며, 멱등성 보장이 필수적입니다.

재전송 설정 예시

Properties config = new Properties();
config.setProperty("bootstrap.servers", "kafka-server:9092");
config.setProperty("key.serializer", StringSerializer.class.getName());
config.setProperty("value.serializer", StringSerializer.class.getName());
config.setProperty("retries", "5");  // 최대 재시도 횟수
config.setProperty("retry.backoff.ms", "1500");  // 재시도 간 지연 시간
config.setProperty("enable.idempotence", "true");  // 멱등성 활성화

KafkaProducer<String, String> sender = new KafkaProducer<>(config);
sender.send(new ProducerRecord<>("data-topic", "event-key", "payload"), (metadata, ex) -> {
    if (ex != null) {
        if (ex instanceof RetriableException) {
            // 복구 가능 오류 처리
        } else {
            // 치명적 오류 기록
        }
    }
});
sender.close();

소비자 측면 재시도 전략

오프셋 수동 커밋과 오류 핸들러를 결합하여 구현합니다. 최대 재시도 후 실패 메시지는 데드 레터 큐(DLQ)로 전달됩니다.

Spring Kafka 오류 처리

@Bean
public ConsumerFactory<String, String> consumerFactory() {
    Map<String, Object> settings = new HashMap<>();
    settings.put(ConsumerConfig.BOOTSTRAP_SERVERS_CONFIG, "kafka-server:9092");
    settings.put(ConsumerConfig.ENABLE_AUTO_COMMIT_CONFIG, false);  // 자동 커밋 비활성화
    return new DefaultKafkaConsumerFactory<>(settings);
}

@Bean
public ConcurrentKafkaListenerContainerFactory<String, String> containerFactory() {
    ConcurrentKafkaListenerContainerFactory<String, String> factory = new ConcurrentKafkaListenerContainerFactory<>();
    factory.setConsumerFactory(consumerFactory());
    
    DefaultErrorHandler errorHandler = new DefaultErrorHandler(
        new DeadLetterPublishingRecoverer(kafkaOperations),
        new FixedBackOff(2000, 4)  // 2초 간격으로 4회 재시도
    );
    factory.setCommonErrorHandler(errorHandler);
    
    return factory;
}

@KafkaListener(topics = "data-topic", containerFactory = "containerFactory")
public void process(ConsumerRecord<String, String> record) {
    try {
        // 비즈니스 로직 실행
    } catch (DataProcessingException e) {
        throw new RetryableException("처리 재시도 필요", e);
    }
}

핵심 고려사항

  • 멱등성 보장: 생산자와 소비자 모두 중복 처리 방지 필요
  • 데드 레터 큐: 지속적 실패 메시지 격리를 위한 DLQ 활용
  • 오류 분류: 일시적 오류(Retriable)와 영구적 오류 구분 처리

태그: kafka 재시도 멱등성 데드레터큐 SpringKafka

7월 6일 18:49에 게시됨