1. 문서 제목
- Kafka 클러스터 구조와 파티션 설계 — 트랜잭셔널 프로듀서부터 토픽 분리 기준까지
2. 기술 개요 요약
Kafka 클러스터는 "파티션 단위로 데이터를 나누는 샤딩"과 "파티션마다 리더-팔로워로 복제하는 replication"이 동시에 적용된 구조다. 이 구조를 이해하면 파티션 수를 늘릴 때의 비용, 토픽을 나누는 기준, 여러 파티션·토픽에 걸친 쓰기를 원자적으로 처리하는 트랜잭셔널 프로듀서, 브로커 장애 시의 대응까지 하나의 그림으로 연결할 수 있다.
3. 핵심 개념 정리
| 개념 | 설명 | 실무 포인트 |
|---|---|---|
| 클러스터 구조 | 파티션은 샤딩(데이터 분할), 파티션 내 리더+팔로워 복제는 replication(Redis Master-Replica와 동일 개념) | 브로커 하나가 죽으면 그 브로커가 리더였던 파티션들에 대해서만 새 리더가 선출됨(failover) |
| idempotent producer vs transactional producer | idempotent producer(enable.idempotence=true)는 같은 파티션 내 재시도 중복 쓰기만 방지. transactional producer는 여러 파티션/토픽에 걸친 쓰기를 하나의 원자적 단위로 묶음 |
컨슈머는 isolation.level=read_committed로 설정해야 커밋 안 된(aborted) 메시지를 걸러낼 수 있음. Kafka 내부 쓰기끼리의 원자성이지 외부 DB/API 호출까지 묶어주진 않음 — DB와 함께 원자적으로 다루려면 Outbox 패턴 필요 |
| 파티션 수 산정 | 파티션이 많을수록 병렬성은 늘지만 브로커의 파일 핸들·메모리 오버헤드, 장애 시 리더 재선출 작업량, 컨트롤러 fail-over 시 메타데이터 로딩 시간이 함께 증가 | Kafka는 파티션 삭제(축소)를 지원하지 않음. 파티션 수를 늘리면 partition = hash(key) % N에서 N이 바뀌므로, 기존에 저장된 데이터가 재배치되는 것이 아니라 앞으로 들어오는 같은 키의 새 메시지가 다른 파티션으로 라우팅되어 그 키의 신-구 메시지 간 순서 보장이 깨질 수 있음. 순서 보장이 중요한 토픽은 초기 설계 시 넉넉하게 산정 |
| 토픽 분리 기준 | ① 이벤트가 나타내는 비즈니스적 사실(fact)의 종류가 다른가(의미 단위) ② 실제로 소비하는 서비스/팀이 다른가(소비자 관심사) | 같은 엔티티의 상태 변화(주문 생성/취소 등)는 오히려 한 토픽에 묶고 엔티티 ID를 파티션 키로 잡아 순서를 보장하는 것이 유리 — "분리 기준"과 반대 방향의 기준임을 함께 기억 |
| 클러스터 간 통신 | 리전 간 재해 복구, 서로 다른 팀이 운영하는 클러스터 사이의 이벤트 공유는 MirrorMaker 2 같은 도구로 토픽을 다른 클러스터로 복제 | 동기 복제가 아니므로 클러스터 간에는 최종적 일관성만 기대 가능. 지연·순서 재배열 가능성을 감안해야 함 |
4. 사용 예시 및 코드 스니펫
클러스터 구조 시각화 (브로커 3대, 파티션 3개, replication factor 3):
브로커 1 브로커 2 브로커 3
┌───────────┐ ┌───────────┐ ┌───────────┐
파티션 0 │ P0 LEADER │───────▶│ P0 팔로워 │───────▶│ P0 팔로워 │
파티션 1 │ P1 팔로워 │◀─────── │ P1 LEADER │───────▶│ P1 팔로워 │
파티션 2 │ P2 팔로워 │◀─────── │ P2 팔로워 │◀───────│ P2 LEADER │
└───────────┘ └───────────┘ └───────────┘
Redis Cluster와 Kafka 클러스터 구조 비교:
| Redis Cluster | Kafka 클러스터 | |
|---|---|---|
| 분산 단위(샤드) | 16384개 고정 해시 슬롯 | 토픽 생성 시 지정한 파티션 수 |
| 복제 단위 | 슬롯(마스터)당 레플리카 N개 | 파티션당 팔로워 N개(replication factor) |
| failover | 마스터 죽으면 레플리카 중 승격 | 리더 죽으면 팔로워(ISR) 중 승격 |
트랜잭셔널 프로듀서 사용 흐름:
producer.initTransactions()
producer.beginTransaction()
producer.send(record1) // topic A
producer.send(record2) // topic B
producer.commitTransaction() // 또는 abortTransaction()
5. 실제 사용 시 주의점 / Best Practice
- 파티션 수를 "공짜로 늘어나는 병렬성"으로 생각하지 말 것. 파일 핸들·메모리 같은 고정비용과, 장애 시 리더 재선출·메타데이터 로딩 같은 장애 복구 시간이 함께 늘어나는 트레이드오프다.
- 트랜잭셔널 프로듀서는 Kafka 내부 쓰기끼리만 원자성을 보장한다. DB 업데이트나 외부 API 호출까지 같은 트랜잭션으로 묶고 싶다면 Outbox 패턴을 별도로 적용해야 한다.
- 토픽을 나눌지 합칠지 결정할 때 "의미 단위가 다른가"와 "소비자 관심사가 다른가"를 먼저 따지고, 순서 보장이 필요한 케이스는 반대로 하나의 토픽 + 엔티티 ID 파티션 키로 묶는다.
- 클러스터 간 복제(MirrorMaker 2)는 동기 복제가 아니므로, 재해복구 설계 시 RPO(복구 시점 목표)에 지연 시간을 반드시 반영해야 한다.
6. 참고자료 / 공식 문서 출처
- Apache Kafka 공식 문서, Transactions/Message Delivery Semantics: https://kafka.apache.org/documentation/#semantics
- Confluent, "Transactions in Apache Kafka": https://www.confluent.io/blog/transactions-apache-kafka/
- Apache Kafka 공식 문서, Geo-Replication(MirrorMaker 2): https://kafka.apache.org/documentation/#georeplication
반응형
'메세지 브로커 > Kafka' 카테고리의 다른 글
| [Kafka] 핵심 원리 정리 — 처리량이 높은 이유, acks, 오토커밋 유실·중복, 리밸런싱 (0) | 2026.07.12 |
|---|---|
| [Kafka] 파티션키·샤딩키로 순서가 보장되는 원리 — 유저 단위로 쪼개는 이유 (0) | 2026.07.12 |
댓글