ZeroBase/CS

Apache Kafka - 분산 스트리밍 플랫폼

Red_Horse 2025. 9. 11. 20:40

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 보유
 
     복제 (Replication)
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