ISR (In-Sync Replicas)
ISR은 Leader와 동기화된 Replica 집합으로, Kafka의 데이터 일관성과 가용성을 결정합니다.
ISR 개념
정의
┌─────────────────────────────────────────────────────────────────┐
│ ISR (In-Sync Replicas) │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 모든 Replica (AR: Assigned Replicas) │
│ ┌───────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ ISR (In-Sync Replicas) │ │
│ │ ┌───────────────────────────────────────────┐ │ │
│ │ │ │ │ │
│ │ │ Leader Follower Follower │ │ │
│ │ │ (Broker1) (Broker2) (Broker3) │ │ │
│ │ │ ✓ ✓ ✓ │ │ │
│ │ │ │ │ │
│ │ └───────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ OSR (Out-of-Sync Replicas) │ │ │
│ │ ┌─────────────────────────┐ │ │ │
│ │ │ Follower (Broker4) │←─────┘ │ │
│ │ │ ✗ (lag 초과) │ 동기화 지연 │ │
│ │ └─────────────────────────┘ │ │
│ │ │ │
│ └───────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
ISR 멤버십 조건
Replica가 ISR에 포함되려면:
1. replica.lag.time.max.ms 내에 Leader에 fetch 요청
기본값: 30000ms (30초)
2. Leader의 log-end-offset을 따라잡음
(최신 메시지까지 복제 완료)
ISR 동작
ISR 축소 (Shrink)
정상 상태:
ISR = [Broker1(L), Broker2, Broker3]
Broker3 지연 발생 (replica.lag.time.max.ms 초과):
┌─────────────────────────────────────────┐
│ Broker1 (Leader) │
│ Log-end-offset: 1000 │
│ │
│ Broker2: offset 1000 ✓ (In-sync) │
│ Broker3: offset 800 ✗ (Lagging) │
└─────────────────────────────────────────┘
ISR 축소:
ISR = [Broker1(L), Broker2]
OSR = [Broker3]
ISR 확장 (Expand)
Broker3이 따라잡음:
┌─────────────────────────────────────────┐
│ Broker1 (Leader) │
│ Log-end-offset: 1200 │
│ │
│ Broker2: offset 1200 ✓ │
│ Broker3: offset 1200 ✓ (Caught up!) │
└─────────────────────────────────────────┘
ISR 확장:
ISR = [Broker1(L), Broker2, Broker3]
OSR = []
ISR 관련 설정
Broker 설정
# Replica lag 임계값 (ISR 제외 기준)
replica.lag.time.max.ms = 30000
# 최소 ISR 수 (acks=all 시 적용)
min.insync.replicas = 2Topic 설정
# Topic별 min.insync.replicas 설정
kafka-configs.sh --alter \
--entity-type topics \
--entity-name my-topic \
--bootstrap-server localhost:9092 \
--add-config min.insync.replicas=2ISR과 Producer acks
acks=all의 동작
acks=all (또는 acks=-1):
Producer → Leader → 모든 ISR에 복제 → ACK
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Producer │────>│ Leader │────>│ ISR 복제 │
│ │ │ │ │ │
│ │<────│ │<────│ 완료 │
│ ACK │ │ │ │ │
└──────────┘ └──────────┘ └──────────┘
min.insync.replicas 효과
RF = 3, min.insync.replicas = 2, acks = all
ISR = 3 (정상):
├── 쓰기 성공 ✓
└── 2개 이상 ISR에 복제됨
ISR = 2:
├── 쓰기 성공 ✓
└── 2개 ISR에 복제됨
ISR = 1:
├── 쓰기 실패 ✗
└── NotEnoughReplicasException
예외 처리
try {
producer.send(record).get();
} catch (ExecutionException e) {
if (e.getCause() instanceof NotEnoughReplicasException) {
// ISR 부족
log.error("Not enough ISR replicas");
// 재시도 또는 대체 처리
}
}ISR 모니터링
JMX 메트릭
파티션별 ISR 크기:
kafka.cluster:type=Partition,name=InSyncReplicasCount,
topic={topic},partition={partition}
Under-replicated 파티션:
kafka.server:type=ReplicaManager,name=UnderReplicatedPartitions
ISR 변화율:
kafka.server:type=ReplicaManager,name=IsrShrinksPerSec
kafka.server:type=ReplicaManager,name=IsrExpandsPerSec
명령행 도구
# 토픽 상세 정보 (ISR 포함)
kafka-topics.sh --describe \
--topic my-topic \
--bootstrap-server localhost:9092
# 출력:
# Topic: my-topic Partition: 0 Leader: 1 Replicas: 1,2,3 Isr: 1,2
# Under-replicated 파티션 확인
kafka-topics.sh --describe \
--bootstrap-server localhost:9092 \
--under-replicated-partitions알림 설정 (Prometheus)
groups:
- name: kafka-isr-alerts
rules:
- alert: KafkaUnderReplicatedPartitions
expr: kafka_server_ReplicaManager_UnderReplicatedPartitions > 0
for: 5m
labels:
severity: warning
annotations:
summary: "Under-replicated partitions detected"
- alert: KafkaISRShrinking
expr: rate(kafka_server_ReplicaManager_IsrShrinksPerSec[5m]) > 0
for: 5m
labels:
severity: warning
annotations:
summary: "ISR is shrinking"ISR 문제 해결
Under-replicated 파티션
# 1. 원인 파악
kafka-topics.sh --describe \
--topic my-topic \
--bootstrap-server localhost:9092
# Replicas: 1,2,3 Isr: 1,2
# → Broker 3이 ISR에서 빠짐
# 2. Broker 상태 확인
kafka-broker-api-versions.sh \
--bootstrap-server broker3:9092
# 3. Broker 로그 확인
grep -i "replica" /var/log/kafka/server.log일반적인 원인
| 원인 | 증상 | 해결 |
|---|---|---|
| 네트워크 지연 | 간헐적 ISR 변화 | 네트워크 확인 |
| 디스크 병목 | 지속적 lag | 디스크 성능 개선 |
| Broker 과부하 | 느린 복제 | 부하 분산 |
| GC pause | 일시적 lag | JVM 튜닝 |
replica.lag.time.max.ms 튜닝
# 너무 짧으면: ISR 빈번한 변화
# 너무 길면: 장애 감지 지연
# 기본값 (30초)
replica.lag.time.max.ms = 30000
# 네트워크 지연이 있는 환경
replica.lag.time.max.ms = 60000
# 빠른 장애 감지 필요
replica.lag.time.max.ms = 10000High Watermark
개념
High Watermark: 모든 ISR에 복제된 마지막 오프셋
┌─────────────────────────────────────────────────────────────────┐
│ │
│ Leader Log: [0][1][2][3][4][5][6][7][8][9] │
│ Follower1 Log: [0][1][2][3][4][5][6][7] │
│ Follower2 Log: [0][1][2][3][4][5][6] │
│ ↑ │
│ High Watermark = 6 │
│ │
│ Consumer는 HW까지만 읽을 수 있음 │
│ (커밋된 메시지만 읽음) │
│ │
└─────────────────────────────────────────────────────────────────┘
Consumer와 HW
// Consumer는 자동으로 HW까지만 읽음
// 별도 설정 불필요
ConsumerRecords<String, String> records = consumer.poll(...);
// HW 이후 메시지는 포함되지 않음
댓글 (0)