백엔드 데이터 인프라 89편 — Kafka Replication (ISR · Leader Election · Unclean)

2026-05-17백엔드 데이터 인프라

백엔드 데이터 인프라 89편. Kafka Replication — leader-follower 비대칭 모델, ISR(in-sync replicas)·committed message·자동 failover, Quorum 접근 vs ISR 접근의 trade-off, Unclean Leader Election 의 위험과 선택까지 풀어쓴 학습 노트. Part 5-2 Design 의 마지막 글.

📚 백엔드 데이터 인프라 · 89편 — Kafka Replication (ISR · Leader Election · Unclean)

이 글은 백엔드 데이터 인프라 시리즈 130편 중 89편이에요. Part 5-2 Design 의 마지막 글. 88편 에서 delivery semantics 보장의 기반replication 이 어떻게 동작하는지가 이번 89편의 주제.

Kafka Replication이 어렵게 느껴지는 이유

분산 시스템에서 가장 깊은 영역이에요. 분산 합의 알고리즘, leader election, split-brain (네트워크 분리로 양쪽이 서로 leader 라고 우김) 같은 무거운 주제가 한꺼번에 엮입니다.

첫째, ISR (In-Sync Replicas) 개념이 새롭다는 점. 전통적 분산 시스템의 Quorum (다수결 투표 합의) 와 완전 다른 접근이라, ISR 이 뭐고 왜 Kafka 가 이걸 선택했는지부터 봐야 합니다.

둘째, Committed 의 정확한 정의. 언제 메시지가 안전한지가 ACK 설정과 ISR 의 조합으로 결정돼요.

셋째, Unclean Leader Election 의 위험. 데이터 손실과 가용성의 trade-off 인데, 잘못 선택하면 조용히 데이터가 사라집니다.

이 글에서 ISR 모델, committed 정의, Quorum vs ISR, Unclean Leader Election 까지 짚어요.

Replication 기본 모델

Topic "payments", Partition 0, Replication Factor 3

           ┌─────────────────────────┐
           │       Broker 1          │
           │  ★ Leader               │  ← 모든 write/read 여기로
           └─────────────────────────┘
                  │
                  │ (자동 복제)
       ┌──────────┼──────────┐
       ▼          ▼          ▼
  ┌─────────┐ ┌─────────┐ ┌─────────┐
  │Broker 2 │ │Broker 3 │ │Broker 4 │
  │Follower │ │Follower │ │Follower │
  └─────────┘ └─────────┘ └─────────┘

각 partition 은 leader 1대와 follower N대로 구성돼요. Replication Factor 는 leader 와 follower 를 합한 값(보통 3)입니다.

동작

쓰기는 항상 leader 로 가고, leader 가 follower 에게 복제 stream 을 보냅니다. 읽기도 기본은 leader 지만, KIP-392 (Kafka Improvement Proposal 392, follower 읽기 기능) 같은 새 옵션을 켜면 follower 에서도 읽을 수 있어요. follower 는 일반 Kafka consumer 처럼 leader 에서 pull 로 가져갑니다.

Replica 위치

Kafka 가 broker 분산과 균등 leader 배치를 자동으로 잡아줘요.

Topic "payments" (12 partitions, RF=3)
Broker 1: P0-leader, P3-follower, P6-follower, P9-leader
Broker 2: P0-follower, P4-leader, P7-follower, P10-leader
Broker 3: P1-leader, P4-follower, P7-leader, P10-follower
Broker 4: P1-follower, P5-leader, P8-leader, P11-follower

partition leader 가 broker 들에 균등 분포되면서 자연스럽게 부하 분산이 됩니다.

ISR (In-Sync Replicas) — Kafka 의 핵심 모델

정의

ISR = leader 와 충분히 sync 된 replica 집합 (leader 포함).

조건은 두 가지예요. 하나는 controller 와의 active session (KRaft (Kafka Raft, ZooKeeper 를 대체한 합의 모듈) heartbeat 으로 살아 있다는 신호), 다른 하나는 leader 를 너무 뒤처지지 않게 따라가는 것(replica.lag.time.max.ms).

Leader 가 ISR 관리

Leader 가 각 follower 의 진행 상태를 추적해요. 일정 시간(replica.lag.time.max.ms, 기본 30초) 동안 leader 를 따라잡지 못한 replica 는 ISR 에서 빠집니다.

Out-of-Sync 가 되는 경우

follower 가 느려서 못 따라가거나, follower 와 leader 사이 네트워크가 막혔거나, follower 가 디스크 I/O 부담을 겪거나, follower 자체가 죽은 경우예요.

동적 변경

초기 ISR = {Broker 1, Broker 2, Broker 3, Broker 4}    (RF=3 + leader)
Broker 4 가 5초 동안 응답 X
→ ISR = {Broker 1, Broker 2, Broker 3}
Broker 4 복구 + 따라잡음
→ ISR = {Broker 1, Broker 2, Broker 3, Broker 4}

ISR 변경은 cluster 메타데이터에 영속화돼서 모든 broker 가 알게 됩니다.

Committed 의 정확한 정의

"A message is considered committed when all replicas in the ISR for that partition have applied it to their log."

핵심은 ISR 모두가 받으면 committed.

  • ISR = {A, B, C} 면 3개 모두 write 완료 → committed
  • ISR 이 {A, B} 로 줄어들면 2개 모두 면 committed (B 는 ISR 이라 안전)
  • ISR = {A} 만 남으면 A 만 write 해도 committed (위험!)

min.insync.replicas 와의 조합

이게 진짜 안전성을 결정합니다. 86편에서 본 producer 설정과 묶어서 봐요.

replication.factor=3
min.insync.replicas=2
acks=all

의미를 풀면, ISR 이 최소 2개일 때만 producer write 를 받아요. ISR 이 2 미만으로 떨어지면 NotEnoughReplicas 에러가 나면서 producer 쓰기가 실패합니다. broker 한 대가 죽어도 ISR 이 2라 여전히 쓸 수 있지만, 두 대가 죽으면 안전을 위해 쓰기를 막아요.

Consumer 측 — Committed 만

Consumer 는 committed 메시지만 봅니다. replica 까지 복제가 안 끝난 메시지는 consumer 에게 보이지 않으니, consumer 가 본 메시지는 안전하다고 보면 돼요.

Quorum vs ISR — 두 가지 접근

Quorum (전통 분산 시스템 — Raft·Paxos·Zab)

Majority vote — 2f+1 replica 중 f+1 이 동의해야 commit. f 개 fail 허용.

Raft (이해하기 쉬운 합의 알고리즘), Paxos (원조 분산 합의), Zab (ZooKeeper Atomic Broadcast) 가 대표적이에요.

장점은 두 가지. 가장 빠른 follower 만 따라와도 commit 되니 latency 가 짧고, 대중적이고 검증된 알고리즘이라 자료도 많습니다.

단점도 분명해요. f 개 fail 을 허용하려면 2f+1 replica 가 필요해서, 1 fail 허용에 3 copy, 2 fail 허용에 5 copy 가 들어가요. 데이터를 5배로 복제하는 건 대용량 영역에서 비실용적입니다.

Kafka 의 ISR 접근

모든 ISR 동의해야 commit. f+1 replica 로 f 개 fail 허용.

장점은 데이터 copy 가 절반이라는 점. 1 fail 을 허용하려면 2 copy 만 있으면 되니, Quorum 의 3 copy 와 비교해 대용량 환경에 잘 맞아요.

단점은 가장 느린 ISR follower 까지 기다려야 한다는 점. 다만 acks=1 로 두면 client 가 원할 때 빨리 응답받을 수 있게 열어둡니다.

왜 Kafka 가 ISR?

대용량 영역(TB·PB 데이터) 에 5× 데이터 비용은 비현실적이에요. Kafka 는 대용량 우선 설계라 ISR 을 골랐고, ZooKeeper 나 etcd 같은 작은 메타데이터 시스템은 데이터 양 자체가 적으니 Quorum (Raft) 이 자연스럽습니다.

한 줄 정리 — Kafka ISR = 대용량 친화 (데이터 절반) + 가장 느린 ISR 까지 기다림 trade-off.

Crashed Node 의 복구

여기서 시험 함정이 하나 있어요. Kafka 는 crashed node 가 모든 데이터를 보존한다고 가정하지 않습니다.

Broker A 가 죽음 (디스크 데이터 일부 손실 가능)
→ 다른 ISR 이 새 leader
→ Broker A 가 복구되면 *완전 re-sync* 후 ISR 재진입

이유는 운영 환경의 현실이에요. 디스크 에러가 가장 흔한 문제고, 매 write 마다 fsync (디스크에 강제 flush 하는 시스템 콜) 를 부르면 성능이 100~1000배 떨어져서 비실용적입니다. 그래서 fsync 없이도 안전하게 동작하는 protocol 로 설계됐어요.

unflushed data 가 있어도 복구 후 다시 동기화하므로 일관성은 유지됩니다.

Unclean Leader Election — 가장 위험한 결정

문제

ISR 의 모든 broker 가 동시에 죽으면 어떻게 될까요? ISR = {} 상태에서 누가 새 leader 가 돼야 할지가 문제입니다.

두 가지 옵션

(A) Clean Leader Election (안전)

unclean.leader.election.enable=false   (기본)

ISR 이 부활할 때까지 partition 이 정지(read/write 둘 다 막힘) 합니다. 데이터 손실은 없지만 가용성도 없어요. ISR 이 전부 죽으면 partition 이 영원히 멈추니, operator 가 수동으로 개입해야 합니다.

(B) Unclean Leader Election (위험)

unclean.leader.election.enable=true

ISR 이 아니어도 살아 있는 replica 가 leader 가 됩니다. 가용성은 살아나지만, 그 replica 가 committed 메시지를 누락했을 수 있어서 과거 데이터 손실이 가능해요.

선택 가이드

금융이나 법적 데이터는 false 로 안전을 우선합니다. 로그·메트릭처럼 약간의 손실을 감내할 수 있는 데이터는 true 로 가용성을 우선해요. 기본값은 false 입니다.

여기서 정말 중요한 자리예요. unclean.leader.election.enable=true 는 데이터 손실 위험을 명시적으로 수용하는 설정이라, 대부분 환경에서는 false 를 권장합니다.

Network Partition

Kafka 는 네트워크가 분리된 환경에서는 가용성을 보장하지 않아요. broker 가 살아 있어도 network partition 으로 controller 와 통신이 끊기면 SDOWN (Subjectively Down, 외부에서 죽은 것으로 판단) 처리됩니다. minority partition 쪽 broker 는 죽은 것처럼 다뤄지고, majority partition 쪽만 계속 동작해요.

CAP theorem (분산 시스템에서 Consistency·Availability·Partition tolerance 중 둘만 보장 가능) 관점에서 Kafka 는 CP 시스템입니다. Consistency 와 Partition tolerance 를 잡고 Availability 를 희생합니다.

실무 운영 권장 설정

# Topic 레벨
replication.factor=3
min.insync.replicas=2
unclean.leader.election.enable=false

# Broker 레벨
replica.lag.time.max.ms=30000        # ISR 판정 (기본)
default.replication.factor=3
# Producer
acks=all
enable.idempotence=true

RF=3, min.insync=2, acks=all = Kafka 안전성의 황금 조합.

모니터링

UnderReplicatedPartitions 메트릭:

$ kafka-topics.sh --describe --under-replicated-partitions

ISR 이 replication factor 보다 적은 partition 을 알려줘요. 이 값이 지속적으로 0 이 아니면 문제입니다.

UnderMinIsrPartitions 는 ISR 이 min.insync.replicas 보다 적은 partition. 쓰기 실패 위험이 임박했다는 신호예요.

시험 직전 한 번 더 — Kafka Replication 함정 압축 노트

  • Replication = partition 단위, replication factor (보통 3)
  • 각 partition = 1 leader + N follower
  • Write/Read 기본 = leader, follower 는 Kafka consumer 처럼 pull
  • Partition leader = broker 들에 균등 분포
  • ISR (In-Sync Replicas) = leader + 충분히 sync 된 follower
  • ISR 조건 = (1) active session (2) replica.lag.time.max.ms 안에 leader 따라잡음
  • ISR 동적 변경 = cluster 메타데이터에 영속화
  • Committed = ISR 모두 받음 → 메시지 안전
  • Consumer = committed 메시지만 본다
  • min.insync.replicas = ISR 최소 수, 안 되면 NotEnoughReplicas 에러
  • 운영 황금 조합 = RF=3 + min.insync.replicas=2 + acks=all
  • 1 broker 죽어도 OK, 2 broker 죽으면 쓰기 실패 (안전 우선)
  • Quorum 접근 (전통) = 2f+1 → f+1 동의 — 데이터 ×3·5
  • Kafka ISR 접근 = f+1 → 모든 ISR 동의 — 데이터 ×2·3 (대용량 친화)
  • ISR 단점 = 가장 느린 ISR 까지 기다림 (latency)
  • Crashed node = 복구 시 완전 re-sync 후 ISR 재진입
  • fsync every write 강제 X (성능 100~1000배 하강 방지)
  • Unclean Leader Election = ISR 모두 죽었을 때 정책
  • false (기본) = partition 정지, 데이터 손실 X, 가용성 X
  • true = 살아 있는 아무 replica leader, 데이터 손실 가능, 가용성 ◯
  • 금융·법적 = false / 로그·메트릭 = true 가능
  • Network Partition = Kafka 는 CP 시스템 (가용성 희생)
  • 모니터링 메트릭 = UnderReplicatedPartitions·UnderMinIsrPartitions
  • Under replicated 지속 = 문제 신호
  • Under min ISR = 쓰기 실패 위험 임박

공식 문서: Kafka Design — Replication 에서 자세한 사양을 확인할 수 있어요.

시리즈 다른 편 (앞뒤 글 모음)

이전 글:

다음 글:

※ 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

답글 남기기

error: Content is protected !!