개요
- Apache Kafka 컨슈머를 사용할 때, 기본적인 개념과 알아야 할 것들을 정리해 보자.
브로커, 토픽, 파티션
- 먼저, broker, topic, partition 에 대해 알아보자.
- 브로커는 Kafka 클러스터를 구성하는 서버이며, Producer 와 Consumer 간에 메시지를 중계한다.
- 하나의 클러스터는 여러 개의 브로커로 구성될 수 있다.
- 토픽은 데이터 스트림을 구분하는 채널 역할이다.
- 프로듀서는 특정 토픽에 메시지를 발행하고, 컨슈머는 특정 토픽을 구독할 수 있다.
- 하나의 토픽은 여러 파티션으로 나뉘어 저장되고, 파티션들은 여러 브로커에 나뉘어 저장된다.
리더 파티션, 팔로워 파티션
- 각 파티션에는 하나의 리더가 있으며, 여러 개의 팔로워로 구성된다.
- 컨슈머는 리더 파티션에서만 메시지를 가져온다.
- 이는 브로커에 장애가 발생했을 때, 팔로워를 리더로 승격시켜 failover 를 하기 위함이다.
파티션이 브로커에 분배되는 과정
- Kafka 는 토픽을 생성할 때 파티션을 각 브로커에게 분배한다.
- 기본적으로 round-robin 을 통해 분배하며, 수동 할당도 가능하다.
파티션이 필요한 이유
- 토픽을 여러 파티션으로 나누어 저장하는 이유가 뭘까?
- 이는 확장성 (성능) 과 안정성을 증대하기 위함이다.
1. 병렬 처리 성능 향상
- 여러 컨슈머가 각각 다른 파티션을 동시에 소비할 수 있어 처리 속도가 증가
2. 부하 분산
- 여러 브로커에 파티션을 분산 저장하여 한 개의 브로커에 과부하 발생 방지
3. 확장성 (Scalability)
- 데이터 증가 시 파티션을 추가하여 더 많은 컨슈머가 동시에 처리 가능
4. 데이터 복제 & 장애 복구 (High Availability)
- 여러 브로커에 파티션을 복제(Replication) 하여 장애 발생 시 자동 복구 가능
파티션의 개수
- 특정 토픽의 파티션의 개수는 늘릴 수만 있고 줄일 수는 없다.
카프카 컨슈머
- 컨슈머는 토픽을 구독하여 브로커에서 메시지를 가져온다.
- 하나의 컨슈머는 여러 파티션을 소비할 수 있으며, 하나의 파티션은 하나의 컨슈머에게만 할당된다.
- 예를 들어, 토픽의 파티션이 1개이고, 이를 구독하는 컨슈머 그룹의 컨슈머가 3개인 경우 2개의 컨슈머는 대기 상태가 된다.
- 컨슈머는 Kafka 브로커에게서 메시지를 직접 가져간다. (pull model)
컨슈머 그룹
- 컨슈머는 컨슈머 그룹 내에서 동작하며, 각 컨슈머는 특정 파티션의 데이터를 담당한다.
- 이를 통해 여러 개의 컨슈머가 하나의 토픽을 처리할 수 있으며 (병렬 처리), 부하 분산 / 확장이 가능하다.
컨슈머 리밸런싱
- 리밸런싱이란?
- 컨슈머 수의 변화, 장애 등에 의해 컨슈머 그룹 내에서 파티션이 재분배되는 과정이다.
- 리밸런싱의 영향
- 리밸런싱이 발생할 경우, 컨슈머가 파티션을 할당받기 전까지 메시지 소비가 중단된다.
- 리밸런싱이 발생한 컨슈머가 읽은 메시지를 커밋하지 못한 경우, 중복 처리가 발생한다.
- 이외에도 여러 문제가 발생하며, 불필요한 리밸런싱을 줄이는 게 Kafka 운영의 중요한 포인트이다.
리밸런싱 문제 해결
- 리밸런싱이 발생하면 컨슈머 그룹에 stop-the-world 현상이 발생한다.
- 이는 실시간성 서비스의 경우 치명적이다.
- 특히, 컨슈머가 여러 개인 경우 (예: 100개) 하나의 컨슈머에만 문제가 생겨도 전체 리밸런싱이 발생할 수 있다.
- 따라서 리밸런싱이 자주 일어나지 않도록 설정해 줘야 한다.
- 이를 해결하기 위해 1. 정적 멤버쉽 방식이 있다.
- 이는 group.instance.id 값을 컨슈머가 보내어 해당 컨슈머가 timeout 되어도 리밸런싱이 발생하지 않도록 한다.
- 단점이 있는데, 실제로 컨슈머가 복귀할 수 없어 리밸런싱이 필요한 상황에도 리밸런싱이 발생하지 않아, 해당 파티션의 consumer lag 이 계속 쌓일 수 있다.
- 또는, 2. cooperative rebalancing 설정을 하면 된다.
- 이는 필요한 partition 만 revoke 하여 재할당 하는 방식이다.
- 1,2의 설정은 같은 consumer group 내의 컨슈머 애플리케이션의 설정을 통해 사용할 수 있다.
spring.kafka.consumer.properties.partition.assignment.strategy:
org.apache.kafka.clients.consumer.CooperativeStickyAssignor
리밸런싱 모니터링
- 리밸런싱은 컨슈머에서 발생하므로, 브로커의 모니터링으로는 확인할 수 없다.
- 컨슈머의 로그를 통해 리밸런싱 여부를 확인해야 한다.
- 또는 브로커의 consumer lag 를 확인하여 간접적으로 모니터링할 수 있다.
kafka consumer 의 모니터링
- kafka exporter 를 prometheus 에 붙일 수 있다.
at least once / exactly once
- 수동 commit 을 하면 at least once 를 보장할 수 있다.
- DB 를 사용해서, 또는 kafka transaction 기능을 통해 exactly once 를 구현할 수 있다.