이전글(https://bangbaeking.tistory.com/161)에서 카프카와 카프카 클러스터에 대해 정리해 보았다.
카프카의 병렬 처리 구조의 핵심인 파티션(Partition), 컨슈머(Consumer), 그리고 컨슈머 그룹(Group)에 대해 더 깊이 알아보려고 한다.
파티션이란?
우리는 Kafka에서 토픽을 생성하고, 해당 토픽에 메시지를 전달한다.
토픽은 데이터를 저장하는 논리적 단위이고, 토픽은 여러개의 파티션으로 나뉠수 있다.
즉, 하나의 토픽은 여러 파티션으로 분할되어 데이터를 저장하고, 여러 파티션을 통해 메시지를 동시에 소비함으로써 병렬성을 높일 수 있다.
그렇다면 토픽으로 들어온 메시지는 어떤 기준에 따라 여러 파티션으로 분배될까?
파티션에 메시지가 어떻게 분배될까?
Kafka는 Producer가 메시지를 보낼때, 해당 메시지를 어떤 파티션에 넣을지 결정해야한다.
이를 Partitioner 라고 한다. Kafka의 Partitioner는 다음과 같은 로직에 따라 메시지를 분배한다.
1. Key가 없는 메시지 구조 (Null Key)
producer.send(new ProducerRecord<>("my-topic", "메시지 내용만"));
이처럼 Key 없이 메시지만 전달하는 경우, Kafka는 라운드 로빈(Round-Robin) 방식으로 메시지를 파티션에 분배한다.
메시지 번호 | 파티션 |
1 | 0 |
2 | 1 |
3 | 2 |
4 | 0 |
... | ... |
2. Key가 있는 메시지 구조
producer.send(new ProducerRecord<>("my-topic", "user123", "로그인 성공"));
Key가 포함된 메시지의 경우, Kafka는 해당 Key의 해시값(Hash Value)을 기반으로 파티션을 지정한다.
예를 들어 "user123"이라는 Key가 있다면, 이 값을 해싱하여 특정 파티션에 매핑한다. 이때 "user123"이라는 Key를 가진 메시지는 항상 같은 파티션으로 전송된다.
이 방식은 특정 Key에 메시지가 집중되면서 일부 파티션에 부하가 쏠릴 수 있다는 단점이 있다.
3. 직접 파티션 지정(명시적)
new ProducerRecord<>("my-topic", 1, "key", "value") // partition 1 지정
Producer가 파티션 번호를 직접 지정할 수도 있다. 이 경우 Kafka는 해당 메시지를 명시한 파티션에 무조건 전송된다.
파티션의 순서 보장
Kafka는 동일한 파티션 내에서만 메시지 순서를 보장한다.
- Key가 있는 경우: 같은 Key는 같은 파티션으로 들어가므로, 해당 파티션 내에서는 순서가 유지된다.
- 직접 파티션을 지정한 경우: 해당 파티션 내 메시지 순서가 보장된다
- Key가 없는 경우: 운드 로빈으로 여러 파티션에 분산되므로, 전체 순서 보장은 되지 않는다.
파티션과 컨슈머
앞서 토픽에 들어온 메시지가 여러 파티션에 어떻게 분배되는지 알아봤다.
그렇다면, 각 파티션에 분배된 메시지는 어떻게 소비될까?
Kafka에서는 파티션에 저장된 메시지를 컨슈머(Consumer)가 읽어간다. 즉, 파티션 단위로 컨슈머가 메시지를 소비하게 된다.
파티션과 컨슈머가 각각 1개씩 존재할 때는 매우 간단하다. 하지만 파티션과 컨슈머의 개수가 많아지면 어떻게 될까?
파티션 수 == 컨슈머 수
- 각 컨슈머는 하나의 파티션을 맡게 된다.
- 가장 이상적인 병렬 처리 구조이다.
파티션 수 > 컨슈머 수
- 일부 컨슈머가 여러 파티션을 담당하게 된다.
- 병렬 처리는 가능하지만, 컨슈머 간 부하가 균등하지 않을 수 있다.
파티션 수 < 컨슈머 수
- 일부 컨슈머는 아무 파티션도 할당받지 못해 대기 상태가 된다.
- 컨슈머 리소스가 낭비될 수 있다.
정리
- Kafka에서 파티션은 병렬 처리의 단위이다.
- 컨슈머 그룹 내부에서 한 파티션은 단 하나의 컨슈머만 읽을 수 있다. (1개의 파티션에 컨슈머 2개는 불가능)
- 따라서 파티션 수 ≥ 컨슈머 수가 병렬성과 자원 효율을 고려할 때 가장 이상적이다.
컨슈머 그룹
Kafka에서는 컨슈머 그룹을 통해 하나의 토픽을 여러 목적으로 독립적으로 소비할 수 있다.
예를들어 A 토픽에 대하 두 개의 컨슈머 그룹이 있다고 가정해보자
- Group Service → 서비스 로직 처리를 위한 컨슈머 그룹
- Group Logging → 로그 기록을 위한 컨슈머 그룹
이 두 그룹은 같은 메시지를 소비하지만, 하나는 서비스 처리, 다른 하나는 로그 저장이라는 서로 다른 목적으로 데이터를 사용한다.
Kafka에서는 동일한 파티션의 메시지라도 컨슈머 그룹이 다르면 서로 간섭 없이 각각의 컨슈머가 메시지를 처리할 수 있도록 되어 있다.
파티션과 브로커
고가용성과 부하분산
Kafka는 토픽 생성 시 각 파티션을 브로커에 자동으로 분산 배치한다.
브로커 수와 파티션 수에 따라 하나의 브로커에 여러 파티션이 할당될 수도 있고, 가능한 한 고르게 분산되도록 Kafka가 내부적으로 조정한다.
예를 들어, 브로커가 3개이고 파티션이 6개라면 Kafka는 다음과 같이 분산할 수 있다
- Broker 1 → Partition 0, 3
- Broker 2 → Partition 1, 4
- Broker 3 → Partition 2, 5
이처럼 Kafka는 가능한 한 브로커 간 균형 있게 파티션을 배치하려고 한다.
컨슈머 리밸런싱(Consumer Rebalancing)
리밸런싱은 컨슈머 그룹 내에서 파티션 할당을 재조정하는 과정을 말한다. 리밸런싱은 다음과 같은 컨슈머 그룹의 구조 변화가 생길 때 자동으로 발생한다.
리밸런싱 발생 조건
- 새로운 컨슈머가 그룹에 추가될 때
- 기존 컨슈머가 그룹에서 나갈 때 (예: 종료, 장애 등)
- 기존 컨슈머의 세션이 만료될 때 (heartbeat timeout)
- 토픽의 파티션 수가 변경되었을 때
리밸런싱의 영향
- 리밸런싱 중에는 일시적으로 메시지 소비가 멈춘다.
- 일부 파티션이 새로운 컨슈머에게 다시 할당되기 때문이다.
- 리밸런싱이 너무 자주 발생하면 서비스 지연이나 소비 중단으로 이어질 수 있다.
파티션 리밸런싱
컨슈머 리밸린싱이 파티션을 어떤 컨슈머가 읽을지를 재조정하는 것이라면, 파티션 리밸런싱은 파티션 자체가 어떤 브로커에 저장될지를 재배치하는 과정이다.
Kafka는 토픽 생성이나 클러스터 변화에 따라 파티션을 여러 브로커에 자동 분산한다. 하지만 상황에 따라 이 분산 구조를 수동으로 조정하거나 재분배해야 할 때도 있다.
리밸런싱 발생 조건
- 초기 토픽 생성 시에는 Kafka가 자동 분산
- 파티션 수를 늘릴 때
- 브로커 추가/제거 등 클러스터 구조 변경
- 수동 재할당(kafka-reassign-partitions.sh) 수행 시
리밸런싱 영향
- 파티션 데이터가 브로커 간에 이동함 → 복제가 발생
- 리더 브로커도 변경될 수 있음 → 잠시 리더 전환 지연 가능성
- 디스크, 네트워크 사용량 증가 → 부하가 높아질 수 있음
- 잘못된 리밸런싱은 클러스터 전체 성능에 악영향을 줄 수 있음
컨슈머 리밸런싱, 파티션 리밸런싱 비교
컨슈머 리밸런싱은 컨슈머 그룹에 컨슈머가 추가/제거 되거나 토픽의 파티션 수가 변경되면 Kafka에서 자동으로 처리해준다.
하지만 파티션 리밸런싱은 수동으로 처리를 해줘야한다. 브로커가 추가되거나 파티션이 추가되도 Kafka는 파티션을 자동으로 재분배 해주지 않는다.
즉, 브로커가 추가되었는데 해당 브로커가 놀고 있을수 있다.
왜 Kafka는 파티션 리밸런싱을 자동으로 해주지 않을까?
데이터 이동은 매우 무겁고 위험한 작업이다
파티션을 옮긴다는 건 브로커 간에 데이터를 복제해서 동기화하고, 기존 리더를 바꿔야 한다는 뜻이다. 이 과정에서 디스크 I/O 폭증, 네트워크 부하 증가 등 매우 많은 리스크가 동반된다.
따라서 파티션 리밸런싱을 자동으로 진행하면 예상하지 못한 상황에 클러스트의 부하가 매우 증가해 문제가 발생할 수 있다.
전체 상태를 보고 판단해야 할 작업이기 때문이다.
Kafka에서는 운영자의 명시적 제어를 중요하게 여긴다.
브로커의 디스크 용량, 복제본의 균형 여부, 장애 복구 중인지, 리더 위치 조정 여부 등 이러한 부분을 Kafka가 자동으로 판단하면 예상치 못하게 리더가 이동하거나 부하 집중이 생길 수 있다.
리밸런싱이 자주 일어나면 시스템이 흔들릴 수 있다
컨슈머 리밸런싱만으로도 메시지 소비가 멈출 수 있는데, 파티션 리밸런싱까지 자동으로 자주 일어나면 서비스의 안정성이 크게 흔들릴 수 있다.
정리
Kafka는 파티션 리밸런싱을 자동화하지 않음으로써 예기치 않은 클러스터 부하, 데이터 손실, 컨슈머 지연을 방지한다. 물론 Cruise Control 같은 외부 도구를 통해 자동화를 구현할 수는 있다.
반면, 컨슈머 리밸런싱은 상대적으로 가벼운 논리적 작업이기 때문에 Kafka가 자동으로 처리한다.
즉,
- 컨슈머 리밸런싱은 "누가 읽을지"를 재할당하는 작업이고,
- 파티션 리밸런싱은 "어디에 저장할지"를 옮기는 무거운 작업이기 때문에 자동으로 진행되지 않는다.
Kafka는 이처럼 경량 작업은 내부에서 자동으로 처리하고, 무거운 작업은 운영자의 판단과 책임 하에 수동으로 진행되도록 설계되어 있다.
'Database , Middleware > Kafka' 카테고리의 다른 글
[Kafka] Kafka의 기본 개념 및 구성 요소(Kafka 클러스터) (0) | 2025.03.09 |
---|
댓글