Kafka

[실전 카프카 개발부터 운영까지] 4. 카프카의 내부 동작 원리와 구현

noahkim_ 2025. 5. 6. 08:19

고승범 님의 "실전 카프카 개발부터 운영까지" 책을 정리한 포스팅 입니다.


1. 카프카 리플리케이션

동작

예제) 토픽 생성

더보기
/opt/bitnami/kafka/bin/kafka-topics.sh --create --topic topic_chat \
--bootstrap-server localhost:9092 \
--replication-factor 2 \
--partitions 2

 

예제) 토픽 메시지 생성

더보기
/opt/bitnami/kafka/bin/kafka-console-producer.sh --topic topic_chat \ 
--bootstrap-server localhost:9092

 

예제) 토픽 조회

더보기
 /opt/bitnami/kafka/bin/kafka-topics.sh --topic topic_chat --describe \
 --bootstrap-server localhost:9092
Topic: topic_chat	TopicId: Xyz123...	PartitionCount: 2	ReplicationFactor: 2	Configs:
	Topic: topic_chat	Partition: 0	Leader: 1	Replicas: 1,2	Isr: 1,2
	Topic: topic_chat	Partition: 1	Leader: 2	Replicas: 2,1	Isr: 2,1

 

항목 값 설명
Partition 파티션 번호 (0, 1)
Leader 해당 파티션의 쓰기 및 읽기 담당 브로커
Replicas 해당 파티션의 모든 복제본을 가진 브로커 목록
ISR
현재 동기화(in-sync) 상태인 복제본 브로커 목록 (복제 성공 중인 것들)

 

예제) 토픽 메시지 세그먼트 조회

더보기
/opt/bitnami/kafka/bin/kafka-dump-log.sh --print-data-log \ 
--files /bitnami/kafka/data/topic_chat-0/00000000000000000000.log
Dumping file: /bitnami/kafka/data/topic_chat-0/00000000000000000000.log
offset: 0 position: 0 CreateTime: 1715408001000 key: user123 payload: Hello!
offset: 1 position: 132 CreateTime: 1715408002100 key: user456 payload: How are you?
offset: 2 position: 278 CreateTime: 1715408003200 key: user123 payload: I'm good.

 

구성

역할 설명
리더 (Leader)
프로듀서/컨슈머의 읽기/쓰기 작업을 담당
- 복제된 파티션들 중 하나가 리더로 선출됨
팔로워 (Follower)
리더의 데이터를 동기화 함
- 리더에 문제가 발생하면, 팔로워 중 하나가 리더로 승격됨

 

예시) 리더/팔로워 확인하기

더보기

'토픽 조회'를 통해 확인 가능

Topic: topic_chat	TopicId: 3mn7GidkQhKY2IkBpN0T2Q	PartitionCount: 2	ReplicationFactor: 2	Configs: 
	Topic: topic_chat	Partition: 0	Leader: 0	Replicas: 1,0	Isr: 0,1
	Topic: topic_chat	Partition: 1	Leader: 0	Replicas: 0,1	Isr: 0,1

 

복제 유지

항목 설명
ISR (In-Sync Replica) 리더와 데이터를 동일하게 복제하고 있는 팔로워들의 집합
리더 역할 ISR 내 모든 팔로워가 메시지를 수신할 때까지 기다리고 감시
팔로워 조건 지속적으로 리더로부터 메시지를 잘 복제해야 ISR에 남을 수 있음
ISR 제외 일정 시간 이상 지연되면 자동으로 ISR에서 제거됨

 

커밋

항목 설명
커밋
ISR 내 모든 팔로워가 해당 메시지를 수신 완료 시, 리더는 내부적으로 "커밋됨" 상태로 표시
하이워터마크
마지막으로 커밋된 메시지의 offset
- 컨슈머는 이 위치까지 읽을 수 있음

 

예시) 하이워터마크 위치 확인

더보기
cat /bitnami/kafka/data/replication-offset-checkpoint
# partition id / high watermark id
topic_chat 0 2 
topic_chat 1 0

 

리더와 팔로워의 단계별 리플리케이션 동작

  • 리더의 감시 작업은 많은 통신을 요구하므로 빠른 성능을 내기 어렵게 함
  • 카프카는 감시 작업에 드는 통신을 최소화할 수 있도록 설계되었음

 

복제 흐름
  1. 리더: 메시지 수신
  2. 팔로워: 메시지 요청 (+오프셋 정보)
  3. 리더: 메시지 응답 (+하이워터마크)
  4. 팔로워: 메시지 수신
    • 하이워터마크 갱신 (리더의 하이워터마크 >= 내 하이워터마크)
  5. 리더: 모든 팔로워들의 수신 완료 확인
    • 모든 팔로워들의 메시지 오프셋 확인
    • 모든 팔로워가 최신 오프셋 도달 ✅ → 메시지 커밋 
    • 모든 팔로워가 최신 오프셋 도달 ❌ → 메시지 커밋 보류 (팔로워가 리더를 따라잡도록 계속 메시지 요청 유도)
    • ➡️ 팔로워가 끊임없이 복제를 시도하면서, 리더와 데이터 일관성을 맞추게 됨
  6. 리더: 커밋 

➡️ ACK 없이 효율적으로 정합성 확보 가능

 

예시

더보기
* 리더: 메시지 발행 받기 (message1)

* 팔로워1 메시지 consume 요청
1. 팔로워1: 메시지 요청 (message1 + 팔로워 메시지 오프셋)
2. 리더: 메시지 응답 (message1 + 리더 하이워터마크)
3. 팔로워1: 메시지 수신 (message1)
- 하이워터마크 갱신

* 팔로워2 메시지 요청
1. 팔로워2: 메시지 요청 (message1)
2. 리더: 메시지 응답 (message1 + 자신의 하이워터마크)
3. 팔로워2: 메시지 수신 (message1)
- 하이워터마크 갱신

* 리더: 모든 팔로워들의 복제 완료 확인
- 커밋
- 하이워터마크 갱신

 

리더 에포크

  • 리더가 바뀔 때마다 1씩 증가하는 버전 번호 (32비트 정수)
항목 설명
목적
데이터 정합성 유지 (리더 변경 전후의 상태 불일치 탐지 역할)
관리 주체 컨트롤러 (리더 선출 및 에포크 관리)
전파 방법
리더 변경 시, 리플리케이션 프로토콜을 통해 팔로워에게 자동 전달됨
메시지 손실 가능성 팔로워가 리더로 승격될 때, 커밋되지 않은 최신 메시지는 손실 될 수 있음
복구 과정에서 역할
하이워터마크 신뢰 불가 시(리더 변경 등), 에포크 + 오프셋 비교로 동기화 정확성 판단
복구 과정 (요약)
1. 팔로워가 리더에게 현재 에포크와 마지막 오프셋 요청
2. 리더는 에포크/오프셋 일치 여부 확인
3. 불일치 시, 리더가 일치하는 지점부터 데이터 재전송 (fetch)
4. 동기화 완료 후 하이워터마크 갱신

 

 

2. 컨트롤러

  • Kafka 클러스터 내에서 리더 선출과 브로커 상태 관리를 담당하는 브로커

 

역할
항목 설명
리더 선출 ISR 내 팔로워 중 하나를 새로운 리더로 지정함
브로커 실패 감지 특정 브로커가 응답 없을 경우, 장애로 인식
메타정보 기록 새로운 리더 정보를 ZooKeeper 또는 KRaft에 기록
정보 전파 모든 브로커에게 변경 사항(리더 변경 등)을 전파함

 

리더 부재 시 영향
  • 리더가 없으면 쓰기 작업이 불가, 전체 작업 실패
  • ➡️ 리더 선출을 빠르게 수행해야 함
항목 내용
브로커 정상 종료 과정
1. 관리자가 브로커 종료 명령어 실행 (SIG_TERM)
2. 브로커가 컨트롤러에게 종료 알림
3. 컨트롤러가 새 리더 선출
4. 리더 정보를 주키퍼에 기록
5. 모든 브로커에게 리더 변경 사항 전파
6. 종료 요청 브로커에 정상 종료 응답
7. 디스크에 저장 후 정상 종료
브로커 비정상 종료 과정
1. 브로커 다운 발생 (SIG_TERM 같은 신호 없이 죽음)
2. 컨트롤러가 감지 (헬스 체크 중 실패)
3. 새 리더 즉시 선출
4. 리더 정보를 주키퍼에 기록
5. 모든 브로커에게 리더 변경 사항 전파
⚠️ 파티션 다운타임 발생
⚠️ 클라이언트 장애 발생 (재시도 매커니즘을 통해 복구 진행)

 

3. 로그 세그먼트

로그 세그먼트

  • 토픽 메시지를 파일 단위로 분할 저장 (로그 파일 하나 = 세그먼트 파일)
  • 메시지가 인입될 때마다 파일에 append됨
  • key, value, offset, size 등을 함께 기록

 

세그먼트 롤링

  • 세그먼트 파일이 너무 커지면 새로운 세그먼트 파일이 생성됨
  • retention.ms: 로그 세그먼트 파일 최대 보관 시간
  • retention.bytes: 로그 세그먼트 파일 최대 크기

 

롤링 정책

구분 삭제 (Delete)
컴팩션 (Compaction)
설정 값 log.cleanup.policy=delete
log.cleanup.policy=compact
동작 방식 오래된 로그 세그먼트 파일을 삭제
최신 데이터만 남기고 압축
삭제 대상 최신 파일은 남기고, 과거 파일부터 삭제
중복된 key에 대해 가장 최신 value만 보관
주요 설정 옵션 없음 (단순 삭제)
- log.cleaner.min.compaction.lag.ms (최소 대기 시간)
- log.cleaner.max.compaction.lag.ms (최대 대기 시간)
사용 목적 오래된 데이터 자체가 필요 없을 때 사용
같은 key의 최신 상태만 유지하고 싶을 때 사용
대표 사용 예시 일반 메시지 토픽 데이터 관리
내부 토픽 관리 (__consumer_offsets)
특이사항 디스크 공간 확보 목적이 큼
과거 데이터가 중요하지 않을 경우에 적합

 

__consumer_offsets 토픽

  • 내부 특수 토픽
  • 각 컨슈머 그룹의 오프셋 커밋 정보 저장
  • key-value 형태 (key: 컨슈머 그룹 - 토픽, value: 오프셋 번호)
  • 컨슈머가 죽었다가 살아나도 이어서 소비할 수 있음