Apache Kafka는 LinkedIn에서 개발된 분산 스트리밍 플랫폼으로, 대용량의 실시간 데이터 스트림을 안정적으로 처리하기 위해 설계된 오픈소스 메시징 시스템입니다.
핵심 특징
- 높은 처리량: 초당 수백만 개의 메시지 처리 가능
- 분산 아키텍처: 여러 서버에 걸친 확장 가능한 구조
- 내구성: 디스크에 데이터를 영구 저장
- 낮은 지연시간: 실시간에 가까운 데이터 처리
- 고가용성: 장애 상황에서도 서비스 지속
Kafka의 핵심 개념
1. Topic (토픽)
메시지가 저장되는 논리적 단위로, 데이터베이스의 테이블과 유사한 개념입니다.
예시: 이커머스 시스템의 토픽들
┌─────────────────┬─────────────────┬─────────────────┐
│ user-events │ order-events │ payment-events │
├─────────────────┼─────────────────┼─────────────────┤
│ • 로그인 │ • 주문 생성 │ • 결제 완료 │
│ • 로그아웃 │ • 주문 취소 │ • 결제 실패 │
│ • 페이지 뷰 │ • 배송 시작 │ • 환불 처리 │
└─────────────────┴─────────────────┴─────────────────┘
2. Partition (파티션)
토픽을 여러 개로 나눈 물리적 단위로, 병렬 처리와 확장성을 제공합니다.
토픽: user-events (3개 파티션)
Partition 0: [msg1] [msg4] [msg7] [msg10]
Partition 1: [msg2] [msg5] [msg8] [msg11]
Partition 2: [msg3] [msg6] [msg9] [msg12]
↑ ↑
과거 최신
3. Producer (프로듀서)
메시지를 Kafka에 전송하는 클라이언트입니다.
# Python 프로듀서 예시
from kafka import KafkaProducer
import json
producer = KafkaProducer(
bootstrap_servers=['localhost:9092'],
value_serializer=lambda x: json.dumps(x).encode('utf-8')
)
# 메시지 전송
producer.send('user-events', {
'user_id': 12345,
'action': 'login',
'timestamp': '2025-01-01T10:00:00Z'
})
4. Consumer (컨슈머)
Kafka로부터 메시지를 읽어오는 클라이언트입니다.
# Python 컨슈머 예시
from kafka import KafkaConsumer
import json
consumer = KafkaConsumer(
'user-events',
bootstrap_servers=['localhost:9092'],
value_deserializer=lambda m: json.loads(m.decode('utf-8'))
)
# 메시지 소비
for message in consumer:
user_data = message.value
print(f"User {user_data['user_id']} performed {user_data['action']}")
5. Consumer Group (컨슈머 그룹)
동일한 토픽을 구독하는 컨슈머들의 논리적 그룹입니다.
토픽: order-events (3개 파티션)
┌─────────────┬─────────────┬─────────────┐
│ Partition 0 │ Partition 1 │ Partition 2 │
└─────────────┴─────────────┴─────────────┘
↓ ↓ ↓
┌─────────────┬─────────────┬─────────────┐
│ Consumer A │ Consumer B │ Consumer C │ ← Consumer Group: analytics
└─────────────┴─────────────┴─────────────┘
각 파티션은 그룹 내 하나의 컨슈머만 읽을 수 있음
Kafka 아키텍처
클러스터 구조
Kafka Cluster
┌─────────────────────────────────────────────────────────┐
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Broker 1 │ │ Broker 2 │ │ Broker 3 │ │
│ │ │ │ │ │ │ │
│ │ Topic A │ │ Topic A │ │ Topic B │ │
│ │ Partition 0 │ │ Partition 1 │ │ Partition 0 │ │
│ │ (Leader) │ │ (Follower) │ │ (Leader) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
↕
┌─────────────────┐
│ ZooKeeper │
│ (Coordinator) │
└─────────────────┘
주요 구성 요소
Broker (브로커)
- Kafka 클러스터를 구성하는 개별 서버
- 메시지 저장 및 클라이언트 요청 처리
- 일반적으로 3개 이상의 브로커로 클러스터 구성
ZooKeeper
- 클러스터 메타데이터 관리
- 브로커 상태 모니터링
- 리더 선출 및 설정 정보 저장
- Kafka 2.8.0부터 ZooKeeper 없이도 실행 가능 (KRaft 모드)
Kafka의 동작 원리
1. 메시지 저장 방식
Log-Based Storage
Kafka는 추가 전용(Append-Only) 로그 방식으로 메시지를 저장합니다.
파티션 내부 구조:
┌───────────────────────────────────────────────────────┐
│ Offset: 0 1 2 3 4 5 6 7 8 │
│ Data: [A] [B] [C] [D] [E] [F] [G] [H] [I] ────→ │
│ ↑ │
│ 새 메시지 추가 위치 │
└───────────────────────────────────────────────────────┘
특징:
- 메시지는 순서대로 저장 (순서 보장)
- 기존 메시지는 수정/삭제 불가 (Immutable)
- 각 메시지는 고유한 Offset 보유
Topic: payments (replication-factor: 3)
Broker 1 Broker 2 Broker 3
┌─────────┐ ┌─────────┐ ┌─────────┐
│Partition│ │Partition│ │Partition│
│ 0 │ │ 0 │ │ 0 │
│(Leader) │ ──→│(Replica)│ ──→│(Replica)│
└─────────┘ └─────────┘ └─────────┘
- Leader: 읽기/쓰기 처리
- Replica: Leader 데이터 복사본 유지
- Leader 장애 시 Replica 중 하나가 새 Leader 선출
2. 메시지 라우팅
파티셔닝 전략
// 1. 라운드 로빈 (기본값)
// 메시지를 순차적으로 파티션에 분배
// 2. 키 기반 파티셔닝
producer.send(new ProducerRecord<>(
"user-events",
user.getId(), // 파티션 키
eventData // 메시지 내용
));
// 같은 user_id는 항상 같은 파티션으로!
3. 오프셋 관리
Consumer Offset
Topic: order-events
Partition 0: [0][1][2][3][4][5][6][7][8][9]
↑
Consumer A가 읽은 마지막 위치 (offset: 3)
Consumer A가 다음에 읽을 메시지: offset 4부터
오프셋 정보는 __consumer_offsets 토픽에 저장
실제 사용 사례
1. 실시간 데이터 파이프라인
로그 수집 시스템
웹 서버들 → Kafka → 실시간 분석 시스템
┌─────────┐ ┌─────────┐ ┌─────────────┐
│ Web 1 │──→│ │──→│Elasticsearch│
├─────────┤ │ Kafka │ ├─────────────┤
│ Web 2 │──→│ Cluster │──→│ Data Lake │
├─────────┤ │ │ ├─────────────┤
│ Web 3 │──→│ │──→│ Monitoring │
└─────────┘ └─────────┘ └─────────────┘
토픽 예시:
- access-logs: 웹 접근 로그
- error-logs: 에러 로그
- performance-metrics: 성능 지표
2. 마이크로서비스 통신
이벤트 기반 아키텍처
주문 서비스 → order-events → 배송 서비스
→ 결제 서비스
→ 알림 서비스
이벤트 예시:
{
"event_type": "order_created",
"order_id": "ORD-123456",
"user_id": 12345,
"amount": 59900,
"timestamp": "2025-01-01T10:30:00Z"
}
3. 실시간 스트림 처리
Kafka Streams 활용
// 실시간 매출 집계
StreamsBuilder builder = new StreamsBuilder();
KStream<String, OrderEvent> orders = builder.stream("orders");
KTable<String, Long> salesByCategory = orders
.groupBy((key, order) -> order.getCategory())
.aggregate(
() -> 0L,
(category, order, total) -> total + order.getAmount()
);
salesByCategory.toStream().to("sales-by-category");
Kafka의 장점과 단점
장점
1. 높은 성능
- 처리량: 단일 브로커로 초당 100만+ 메시지 처리
- 지연시간: 밀리초 단위의 낮은 지연시간
- 확장성: 브로커 추가로 선형적 성능 향상
2. 내구성과 신뢰성
- 데이터 보존 정책
- 시간 기반 : 7일간 데이터 보존
- 크기 기반 : 1GB까지 데이터 보존
- 압축 : 키별 최신 메시지만 유지
3. 유연한 메시지 소비
- 리플레이: 과거 메시지 재처리 가능
- 병렬 처리: 파티션별 독립적 소비
- 다중 컨슈머: 여러 애플리케이션이 동시 소비
단점
1. 복잡성
- 클러스터 설정 및 운영의 복잡함
- ZooKeeper 의존성 (구버전)
- 모니터링 및 튜닝 필요
2. 순서 보장 제약
- 파티션 내에서만 순서 보장
- Partition 0: [A1] [A2] [A3] ← 순서 보장 O
- Partition 1: [B1] [B2] [B3] ← 순서 보장 O
- 전체 토픽에서는 순서 보장 X
- 전체: A1, B1, A2, B2, A3, B3 (순서 불보장)
3. 메시지 크기 제한
- 기본값: 1MB per message
- 대용량 메시지 처리 시 별도 설계 필요
'ZeroBase > CS' 카테고리의 다른 글
| 해시테이블(HashTable) (0) | 2025.09.13 |
|---|---|
| Map과 Set (0) | 2025.09.13 |
| TEXT와 BLOB - 대용량 데이터 저장 타입 (0) | 2025.09.11 |
| CHAR vs VARCHAR - 문자열 타입 (0) | 2025.09.11 |
| 데이터베이스 기초 - 엔터티, 릴레이션, 속성 (0) | 2025.09.11 |