피드로 돌아가기
컬리 기술블로그Backend
원문 읽기
분산 시스템 환경에서 Kafka Consumer 오프셋 이동하기
Kurly 주문팀이 Spring Kafka의 ConsumerSeekAware 인터페이스를 활용해 컨슈머 그룹 중단 없이 오프셋을 동적으로 이동하는 무중단 재처리 메커니즘 구축
AI 요약
Context
물류 Kafka 클러스터에 대한 관리자 권한이 없었던 주문팀은 오프셋 변경 시 외부 팀의 도움이 필요했다. 더 심각하게는 기존 Kafka Admin API(alterConsumerGroupOffsets)를 사용하려면 컨슈머 그룹을 완전히 중단해야 했으므로, 실시간 배송 알림 서비스인 '컬리나우'의 가용성이 저하되었다. 컨슈머 중단 후 메시지 Lag 처리 지연과 같은 토픽을 구독하는 다른 컨슈머까지 영향을 받는 문제가 발생했다.
Technical Solution
- ConsumerSeekAware 인터페이스 기반 오프셋 제어: Apache Kafka Consumer#seek(..) API를 Spring Kafka에서 추상화한 ConsumerSeekAware와 ConsumerSeekCallback을 사용해 오프셋을 이동
- AbstractConsumerSeekAware 헬퍼 클래스 도입(Spring Kafka 2.3+): 토픽 파티션별로 오프셋 이동 콜백을 등록/제거할 수 있도록 추상화
- 폴링 전 자동 콜백 처리: KafkaMessageListenerContainer가 폴링 전에 seeks 대기열(BlockingQueue)에 쌓인 오프셋 이동 요청을 processSeeks()로 자동 처리해 그룹 중단 회피
- Spring Kafka 3.2.4와 kafka-clients 3.7.1 사용: Spring Boot 3.3.4 환경에서 특정 컨슈머 그룹만 선택해 오프셋을 이동할 수 있도록 기존 이슈 GH-2302 해결
- 독립적인 오프셋 관리 기능: 권한 요청 없이 컨슈머 담당자가 애플리케이션 내부 로직으로 오프셋을 제어할 수 있게 구현
Key Takeaway
분산 시스템에서는 외부 의존성(권한 요청, 다른 팀의 개입)을 제거하면서 동시에 시스템 중단을 최소화하는 설계가 필수다. 기술의 내부 동작 방식(Consumer#seek의 타이밍, 폴링 라이프사이클)을 이해하면 추상화 레이어를 활용해 더 효과적인 솔루션을 찾을 수 있다.
실천 포인트
Spring Kafka를 사용하는 마이크로서비스 환경에서 메시지 재처리가 필요할 때, ConsumerSeekAware를 상속해 오프셋 이동 콜백을 등록하면 컨슈머 그룹을 중단하지 않고도 특정 토픽 파티션의 오프셋을 선택적으로 변경할 수 있다. 이를 통해 외부 권한 의존을 제거하고 컨슈머 중단에 따른 가용성 저하 및 연쇄 영향을 완전히 방지할 수 있다.