
Kafka Consumer는 데이터를 읽은 후, “어디까지 읽었는지”를 표시하기 위해 offset commit을 수행한다.
Commit된 offset은 내부 토픽 __consumer_offsets에 저장되며 장애나 재시작 시 Consumer가 이어서 읽을 수 있도록 기준점 역할을 한다.
만약 commit이 잘못 관리되면 두 가지 문제가 발생할 수 있다.
Kafka에서는 offset commit을 자동(Auto) 과 수동(Manual) 두 방식으로 지원한다.
Auto Commit은 enable.auto.commit=true로 설정하면 Consumer가 일정 주기마다 자동으로 commit을 수행하는 방식이다.
이 주기는 auto.commit.interval.ms로 지정 할 수 있다.
즉, Consumer가 데이터를 읽더라도 즉시 commit되지 않고 일정 시간이 지난 뒤 poll() 과정 중 commit된다.
이 경우, commit이 지연될 수 있으므로 Consumer가 장애나 리밸런싱으로 재시작될 때 중복 처리가 발생할 수 있다.
Manual Commit은 개발자가 명시적으로 commit 시점을 제어할 수 있는 방식이다.
이 방식은 정확한 처리 보장을 위해 일반적으로 선호된다.
동기 방식은 정확성에, 비동기 방식은 처리 속도에 유리하다.
따라서 메시지 손실이 허용되지 않는 경우엔commitSync(),
로그성 데이터나 처리량이 중요한 경우엔commitAsync()를 선택한다.
기본적으로 Consumer Group은 Coordinator가 파티션을 자동 분배하지만,
특정 파티션만 읽어야 하는 상황에서는 수동으로 파티션을 직접 할당(assign) 할 수 있다.
예를 들어, 배치 처리 시 특정 키 범위를 담당하는 파티션만 특정 Consumer가 읽도록 설정할 수 있다.
TopicPartition partition0 = new TopicPartition("topicA", 0);
consumer.assign(Arrays.asList(partition0));
이렇게 하면 해당 Consumer는 오직 파티션 0만 읽게 된다.
Coordinator를 통한 리밸런싱이 발생하지 않으며, 완전히 독립적으로 동작한다.
특정 메시지가 누락되었거나, 재처리가 필요한 경우
seek() 메서드를 사용해 특정 offset부터 다시 읽을 수 있다.
TopicPartition partition1 = new TopicPartition("topicA", 1);
consumer.assign(Arrays.asList(partition1));
consumer.seek(partition1, 6L);
위 코드는 topicA의 파티션 1에서 offset 6부터 다시 데이터를 읽기 시작한다.
이 방식은 로그 복구나 테스트, 유지보수 작업에서 자주 사용된다.
단, 같은 group.id를 사용하는 Consumer가 commit을 수행하면
__consumer_offsets 토픽의 기록이 갱신되므로 주의해야 한다.
https://github.com/develkkm/kafka-from-0/tree/kafka-core/consumers