| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | |||
| 5 | 6 | 7 | 8 | 9 | 10 | 11 |
| 12 | 13 | 14 | 15 | 16 | 17 | 18 |
| 19 | 20 | 21 | 22 | 23 | 24 | 25 |
| 26 | 27 | 28 | 29 | 30 | 31 |
- JPA
- springsecurity
- 공통규약
- SEQUENCE
- OOP
- DDD
- model
- 전전긍긍
- 단위테스트
- Ajax
- 문제선택근거
- 사면초가
- index
- AOP
- MVC요청플로우
- 로그백
- 설정세팅
- 공통기술
- 커뮤니티서버
- 클린아키텍처
- MVC
- 이벤트핸들러등록
- TDD
- SpringLegacy
- string
- 디스크i/o
- 냄새라도
- 이벤트핸들러this
- JDBC
- Transaction
- Today
- Total
개발이군고구마
[Kafka/Redis] Kafka 개념 본문
1주차 - Kafka 개념
2주차 - Kafka 설치
3주차 - Kafka와 Spring
4주차 - Kafka 메트릭
5주차 - Redis 개념
6주차 - Kafka/Redis를 활용한 실시간 트랜잭션 집계 서비스
1) Kafka는 무엇을 해결하려고 만들어졌나
Kafka는 “이벤트(사실/변화/로그)”가 계속 발생하는 시스템에서, 그 이벤트를
- 지속적으로 저장하고
- 여러 소비자가 각자 필요한 방식으로 읽어 가게 해주는
- 분산 이벤트 스트리밍 플랫폼이다.

즉, 단순 메시지 큐를 넘어서
- (1) 오래 보관되는 로그
- (2) 여러 소비자가 독립적으로 읽는 구조
- (3) 높은 처리량/확장성 을 목표로 한다.
Kafka의 토픽(topic)은 “테이블”이라기보다 **끝없이 append 되는 로그(신문 연재/거래 원장)**에 가깝다.
소비자는 “마지막으로 읽은 지점(오프셋)”만 기억하면 된다.
2) Kafka의 데이터 모델: Topic → Partition → Log(세그먼트) → Offset

2-1. Topic: 이벤트가 모이는 논리적 통로
- Topic: 이벤트를 분류하는 논리 단위(주문, 결제, 클릭로그 등).
- 한 Topic은 보통 여러 Partition으로 나뉜다(확장/병렬 처리 목적).
2-2. Partition: Kafka 확장성의 핵심(병렬 처리 단위)
- Partition은 “append-only 로그”다. 메시지는 뒤에만 계속 붙고(append), 중간 수정은 없다.
- Topic의 처리량은 결국 Partition 수로 스케일된다(프로듀서/컨슈머 병렬화).

2-3. Offset: “파티션 안에서의 메시지 주소”
- Offset: 파티션 로그에서 메시지의 위치(0,1,2… 증가).
- “전체 토픽의 전역 순서”는 보장되지 않는다. 대신 파티션 내부에서는 순서가 보장된다(같은 파티션에 들어간 것들끼리).
→ 그래서 “순서가 중요한 이벤트”는 **같은 키(key)**로 같은 파티션에 들어가게 설계하는 경우가 많다.
orders-topic, partition 0:
offset 0: {"order_id": "A", "user": "김철수", "amount": 10000}
offset 1: {"order_id": "B", "user": "이영희", "amount": 20000}
offset 2: {"order_id": "C", "user": "박민수", "amount": 15000}
offset 3: {"order_id": "D", "user": "최지은", "amount": 30000}
offset 4: {"order_id": "E", "user": "정우성", "amount": 25000}
2-4. Segment(Log Segment): 파티션 로그의 “물리 파일 묶음”
파티션 로그는 내부적으로 하나의 거대한 파일이 아니라, 일정 크기/시간 단위로 잘린 세그먼트 파일들의 집합이다.
#file
$ls /data/kafka/kafka-log-a/test_topic-0
000000123453.index
000000123453.timeindex
000000123453.log
000007735204.index
000007735204.timeindex
000007735204.log
leader-epoch-checkpoint
- 실제 메시지: *.log
- 빠른 탐색용 인덱스: *.index, *.timeindex
- 세그먼트는 시간이 지나면 “roll(새 파일로 교체)”되고, 보관 정책(retention/compaction)에 따라 삭제/정리된다.

3) Producer: 어떻게 파티션을 고르고, 왜 배치가 중요한가
3-1. Record(메시지) 구조
프로듀서가 보내는 단위는 보통 이렇게 생각하면 된다.
- key(선택): 파티션 결정/정렬에 영향
- value(필수): 실제 데이터(payload)
- headers(선택), timestamp 등
Kafka는 네트워크로 보내기 위해 직렬화(serializer)가 필요하다.



3-2. Partitioner: 어느 파티션으로 보낼까
- 키가 있는 경우: 일반적으로 같은 키는 같은 파티션으로 간다(순서 보장/집계 용이).
- 메시지에 key = "k1"이 있다면
- hash("k1") % 2 = 0 → Partition 0으로 할당
- 메시지에 key = "k2"가 있다면
- hash("k2") % 2 = 1 → Partition 1로 할당
- 중요: 같은 key를 가진 메시지는 항상 같은 partition으로
- 키가 없는 경우: 과거엔 라운드로빈 성격이 강했지만, “배치 효율”을 높이기 위해 sticky(스티키) 파티셔닝이 도입되어 기본 동작이 바뀐 흐름이 있다. KIP 문서에서도 sticky partitioner가 기본 파티셔너가 되었다고 설명한다
⚠️ 주의
“키가 같으면 반드시 같은 파티션”은 기본 파티셔너의 일반적 특성이지만, “어떤 파티셔너를 쓰는지/토픽 파티션 수가 바뀌었는지”에 따라 결과가 달라질 수 있다. 운영 중 파티션 수 변경은 키→파티션 매핑을 바꿔 순서 가정이 깨질 수 있으니 신중해야 한다.
3-3. Batch(배치)와 성능
Kafka 프로듀서는 보통 레코드를 모아서 배치로 전송한다.
배치가 커질수록 네트워크/IO 효율이 좋아지지만, 너무 오래 모으면 지연(latency)이 늘어난다. 그래서 linger.ms 같은 “조금 기다렸다가 묶어 보내는” 튜닝이 자주 등장한다.

4) Broker & Cluster: 확장·고가용성을 만드는 운영 단위
4-1. Broker와 Cluster
- Broker: Kafka 서버 프로세스(데이터 읽기/쓰기, 파티션 리더/팔로워 역할 수행).
- Cluster: 여러 Broker의 집합. 보통 장애 허용을 위해 다수 구성.
- RF : N개의 Broker가 있으면 RF는 최대 N까지 사용하여 Topic 생성, 각 partition이 가야하는 broker 개수가 정해져있기 때문에 장애 대비를 위해 1개 더 만들어 놓는 것을 권장



4-2. ZooKeeper vs KRaft(요즘 Kafka 운영에서 매우 중요)
원문에는 ZooKeeper 설명이 있지만, 최근 Kafka는 KRaft 모드로 “메타데이터/컨트롤 플레인”을 Kafka 내부로 통합하는 방향이 명확하다. KRaft 모드에서는 ZooKeeper 의존성이 제거되고, 컨트롤러(Quorum Controller)가 Raft 기반으로 메타데이터를 관리한다.

4-3) Page Cache
브로커의 유저스페이스 힙 메모리 에 저장할 필요 없이, 다이렉트로 네트워크 버퍼에 있는 데이터를 OsPageCache로 그냥 전송할 수 있음

5) Replication, ISR, HWM: “데이터를 잃지 않기”의 핵심 메커니즘
5-1. Replication(복제) 기본
각 파티션은 복제 계수(replication factor, RF)에 따라 여러 브로커에 복제된다.
- Leader replica: 프로듀서/컨슈머가 기본적으로 읽고/쓰는 대상
- Follower replica: 리더의 로그를 복제하며 장애 시 리더 승격 후보


5-2. ISR(In-Sync Replicas)와 HWM(High Watermark)
- ISR: 리더를 충분히 따라잡고 있는 “동기화된 복제본 집합”
- HWM: 컨슈머에게 “커밋된(committed) 데이터”로 공개 가능한 경계(대략 “ISR에 안전하게 반영된 지점”)
→ 컨슈머는 보통 “커밋된 레코드”만 읽는 흐름으로 이해하면 사고가 적다(정확한 동작은 설정/클라이언트에 따라 달라질 수 있음).


주키퍼에게 ISR을 팔로우업해서 알려주고 cluster 내의 다른 Broker 정보를 모니터링
6) acks · min.insync.replicas · unclean leader election: 내구성 vs 가용성 트레이드오프
Kafka에서 “유실 가능성/중복 가능성” 논의는 결국 아래 3개를 같이 봐야 한다.
6-1. acks(프로듀서 내구성 레벨)
Kafka 문서에서 acks는 “프로듀서가 성공으로 간주하기 위해 필요한 확인(acknowledgment) 수준”이라고 정의한다.

- acks=0: 서버 응답을 기다리지 않음(가장 빠르나 유실 위험 큼)
- acks=1: 리더에만 기록되면 성공(리더 장애 타이밍에 따라 유실 가능)
- acks=all(-1): ISR에 충분히 복제될 때까지 기다림(가장 강한 내구성, 대신 지연/실패 가능성 증가)
6-2. min.insync.replicas(얼마나 복제돼야 “쓰기 허용”할까)
토픽 설정 min.insync.replicas는 acks와 함께 “더 강한 내구성 보장”을 만들기 위한 핵심 레버다. Kafka 문서에서도 RF=3, min.insync.replicas=2, acks=all 같은 조합을 대표 시나리오로 설명한다.
6-3. unclean.leader.election.enable(최후의 리더 선출)
unclean.leader.election.enable은 “ISR에 없는 복제본도 최후의 수단으로 리더가 되게 할지”를 결정하며, 그렇게 하면 데이터 유실 가능성이 있다고 Kafka 문서에 명시돼 있다.
✅ 운영 관점 한 줄 요약
- **내구성(유실 방지)**을 올리려면: acks=all + min.insync.replicas 강화 + unclean election 비활성(보수적으로)
- **가용성(멈추지 않기)**을 올리려면: 반대로 더 느슨한 설정(단, 그 대가가 “유실/중복/불일치”임)
[Replica Failure]
ISR은 Leader가 관리함 (Follower 장애 여부를 Zookeeper에게 알림)
Zookeeper가 Leader 장애가 있는지 감지하고 컨트롤러가 새로운 Leader를 선출하고 ISR 리스트를 Zookeeper에게 기록하고 Leader 변경

Partition Leader 가 없으면 Leader가 선출될때까지 해당 Partition 사용할 수 없음
[Replica Recovery]
Leader 가 가지고 있었던 데이터 중에 복제본이 아직 그 데이터를 commit 하지 못한 경우에 Leader 죽음
-> Producer는 ack를 못 받았기 때문에 계속해서 retry
-> 그러나 Leader가 된 Follower 에서 commit 이 안된 데이터를 버리지 않게되어 중복 (idempotence false)
ack=1 인 옵션의 경우에는
-> 데이터 유실이 발생할 수도 있음


7) Consumer & Consumer Group: 병렬 소비와 오프셋 관리
7-1. Consumer Group과 “파티션 할당”

- 한 파티션은 같은 컨슈머 그룹 내에서 동시에 한 컨슈머에게만 할당된다(병렬 소비 단위=파티션).
- 서로 다른 그룹은 같은 토픽을 각자 독립적으로 소비할 수 있다(예: 마케팅 그룹, 정산 그룹).
브로커 1: Partition 0, 1
브로커 2: Partition 2, 3 ← Group Coordinator 역할도 수행
브로커 3: Partition 4, 5
컨슈머 A (Group Leader):
- 브로커 2(Coordinator)와 통신하여 그룹 관리
- 파티션 0, 2, 4 할당받음
- 실제 데이터는 브로커 1, 2, 3에서 각각 가져옴
컨슈머 B:
- 브로커 2(Coordinator)와 통신하여 그룹 관리
- 파티션 1, 3, 5 할당받음
- 실제 데이터는 브로커 1, 2, 3에서 각각 가져옴
7-2. __consumer_offsets(내부 토픽)
Kafka는 컨슈머 그룹의 오프셋 커밋 정보를 내부 토픽 __consumer_offsets에 저장한다(원문 메모의 “consumer_offsets”는 보통 이 토픽을 의미).
이 토픽도 결국 Kafka의 일반 토픽처럼 파티션을 가지며, 그룹 코디네이터가 해당 파티션을 관리한다(운영/모니터링 시 매우 중요).


7-3. 리밸런싱(Rebalancing)과 Heartbeat
컨슈머는 그룹에 “살아있다”는 신호(heartbeat)를 보내고, 멤버 변동(추가/이탈/장애)이나 토픽 파티션 변화가 있으면 리밸런싱이 일어난다. 리밸런싱 중에는 할당이 재조정되며, 전략에 따라 “일시 정지” 체감이 생길 수 있다.

7-4. Partition Assignment Strategy(할당 전략)
원문에 나온 Range / RoundRobin / Sticky / Cooperative Sticky는 “어떻게 파티션을 분배하고, 리밸런싱 충격을 얼마나 줄이느냐”의 차이다.
- Range: 토픽별 파티션 범위를 연속 구간으로 나눠 할당(토픽이 여러 개면 편향이 생길 수 있음)
- RoundRobin: 파티션을 번갈아 배치(균등해 보이지만 토픽/구성에 따라 들쭉날쭉 가능)
- Sticky: 기존 할당을 최대한 유지하려고 노력(불필요한 이동 감소)
Consumer C0: - orders-topic: 파티션 0 - payments-topic: 파티션 0 Consumer C1: - orders-topic: 파티션 1 - payments-topic: 파티션 1 Consumer C2: - orders-topic: 파티션 2 - payments-topic: 파티션 2 - Cooperative Sticky: “한 번에 다 뺏고 다시 나눠주기”가 아니라, 점진적으로 재조정해 스톱 시간을 줄이는 방향

8) Exactly-Once Semantics(EOS): “정확히 한 번 처리”는 언제 성립하나
EOS는 말이 흔하지만, Kafka에서는 보통 read → process → write 파이프라인에서 “커밋된 레코드 기준으로 중복/유실 없이 처리”를 목표로 한다. 이를 위해 idempotent producer + transactions 조합을 사용한다는 것이 핵심이다(생산자 트랜잭션 사용 시 transactional.id 설정이 필요).

- Idempotent Producer(멱등 생산자): 재시도(retry)로 인해 같은 레코드가 중복 저장되는 위험을 줄임
- Transactions(트랜잭션): “소비한 것”과 “생산한 것”을 하나의 원자적 단위로 묶어, 파이프라인의 일관성을 강화
✅ 오해 방지
EOS는 “세상 모든 상황에서 절대 중복이 없다”가 아니라, 특정 조건(트랜잭션/설정/커밋 모델) 하에서 Kafka가 제공하는 강한 보장 모델이다.
9) Kafka Connect · Schema Registry · Streams/ksqlDB: 주변 생태계 한 번에 보기
9-1. Kafka Connect
Kafka Connect는 외부 시스템(DB, S3, ES 등)과 Kafka 사이를 연결하는 표준 통합 런타임이다.
- Source Connector: 외부 → Kafka
- Sink Connector: Kafka → 외부
- Worker/Task 구조로 병렬 처리/확장

9-2. Schema Registry(스키마 관리)
메시지를 “그냥 JSON”으로 흘리면 편하지만, 시간이 지나면 필드 변경/호환성 문제로 장애가 난다.
Schema Registry(특히 Avro/Protobuf/JSON Schema 계열)는 스키마를 중앙에서 버저닝하고 호환성 규칙을 적용해, 데이터 계약(contract)을 운영 가능하게 만든다.



9-3. Kafka Streams / ksqlDB
- Kafka Streams: 애플리케이션 코드(라이브러리)로 스트림 처리를 구현
- ksqlDB: SQL로 스트리밍 처리를 정의/운영(머티리얼라이즈드 뷰 등)


Kafka는 ksqlDB을 consume -> 쿼리로 데이터를 변환해서 kafka에 넣어줌 (=produce)
✳ 출처
- 주요 개념
https://velog.io/@kidae92/Apache-Kafka-%EC%A3%BC%EC%9A%94-%EC%9A%94%EC%86%8C1Producer-Consumer-Topic
- 주키퍼
https://velog.io/@kidae92/Apache-Kafka-%EC%A3%BC%EC%9A%94-%EC%9A%94%EC%86%8C2
- 파티션 / 복제
https://velog.io/@hyun6ik/Apache-Kafka-Producer
- kafka 심화 개념
https://dortmoot.tistory.com/131
- Replication
https://damdam-kim.tistory.com/17
- ksqlDB
https://yeji-shin.github.io/kafka/2022/08/28/17.-Kafka-Streams,-ksqlDB.html
'SERVER > Kafka' 카테고리의 다른 글
| [Kafka/Redis] Spring for Apache Kafka (0) | 2026.02.22 |
|---|---|
| [Kafka/Redis] Kafka 설치 (0) | 2026.02.18 |
| [Redis/Kafka 이용한 대용량 트래픽 예약 및 쿠폰 발급 서비스] 3. Kafka와 Redis로 동시성, 대량 트래픽 제어 (0) | 2025.03.24 |
| [Redis/Kafka 이용한 대용량 트래픽 예약 및 쿠폰 발급 서비스] 2.대용량 트래픽을 견디기 위한 방법 고민 (0) | 2025.03.24 |
| [Redis/Kafka 이용한 대용량 트래픽 예약 및 쿠폰 발급 서비스] 1.멀티 스레드의 동시성을 고려하지 못한 기존 구조 (0) | 2025.03.02 |
