Data & Platform/Event Streaming

Kafka - 13. MirrorMaker 2

MirrorMaker 2 — 클러스터 경계를 넘는 복제, 그리고 offset 동기화의 함정

서울 리전의 Kafka 클러스터가 장애 났다. DR 사이트(도쿄)에 복제해둔 토픽 데이터는 살아 있다. 하지만 장애 복구팀이 가장 먼저 듣는 질문은 이것이다: "consumer offset은요?" 데이터는 복제됐지만, consumer 그룹이 어디까지 읽었는지는 복제되지 않았다. 수천 개의 partition에 대해 consumer가 마지막으로 읽은 위치를 모른다 — 백로그를 처음부터 다시 처리하거나, 하루 전 체크포인트로 수동 복구해야 한다.

이것이 MirrorMaker 1 시절의 현실이었다. MirrorMaker 2(MM2)는 이 문제를 근본적으로 다시 설계했다 — 데이터만 복제하는 것이 아니라, consumer offset, 토픽 설정, ACL까지 함께 옮기는 Connect 기반 복제 프레임워크로. 이 설계가 만드는 이점(완전한 DR)과 trade-off(복제된 토픽 이름 변형, offset 동기화의 전제 조건, 설정 일관성 함정)은 MM2를 프로덕션에 쓸 때 반드시 짚어야 할 지형이다. MM2가 어떻게 구성되고, offset 동기화가 어떤 전제 위에서 동작하며, 어느 순간 자동화가 멈추는지를 추적한다.

본문은 Kafka의 클러스터 내 복제(intra-cluster replication, ISR/HW)가 아닌 클러스터 간 복제(inter-cluster replication)를 다룬다. 클러스터 내 복제는 06 replication 참조.

MM2는 Connect 위에 구축된 크로스 클러스터 복제 프레임워크다

MM2는 서로 다른 Kafka 클러스터 간에 토픽 데이터, 토픽 설정, consumer 그룹 offset, ACL을 복제하는 도구다. 핵심은 Kafka Connect 프레임워크 위에 구축됐다는 점 — Connect의 task 분산, 장애 복구, 내부 topic 기반 상태 저장을 그대로 상속받는다. (10. connect 참조)

MM2는 세 가지 커넥터로 구성된다:

flowchart TD
    subgraph MM2["MirrorMaker 2 (Connect 기반)"]
        SC["MirrorSourceConnector<br/>토픽 데이터 + 설정 + ACL 복제"]
        CC["MirrorCheckpointConnector<br/>consumer offset 체크포인트 + 변환"]
        HC["MirrorHeartbeatConnector<br/>연결 상태 모니터링"]
    end
    SRC["source cluster<br/>(예: us-west)"] --> SC
    SRC --> CC
    SRC --> HC
    SC --> TGT["target cluster<br/>(예: us-east)"]
    CC --> TGT
    HC --> TGT
커넥터 역할 기본 활성화
MirrorSourceConnector source topic의 record를 target으로 복제. 토픽 설정·ACL도 동기화
MirrorCheckpointConnector source consumer 그룹의 offset을 target 기준으로 변환해 checkpoint topic에 기록. sync.group.offsets.enabled=true 시 target의 __consumer_offsets에 직접 기록 예 (단, offset 동기화는 기본 비활성화)
MirrorHeartbeatConnector target cluster에 heartbeat을 주기적으로 발행하여 연결 상태를 추적 가능하게 함

MirrorMaker 1은 단순한 "source consumer + target producer" 조합이었다. offset 동기화, ACL 복제, 자동 토픽 감지, 루프 방지 기능이 없었다. MM2는 KIP-382(Kafka 2.4)에서 도입됐다. (KIP-382)

복제 흐름(replication flow) — 방향성이 있는 데이터 이동

MM2의 핵심 단위는 replication flow다. {source}->{target} 형식으로 정의하며, 방향성이 있다 — 양방향 복제가 필요하면 두 flow를 각각 활성화해야 한다. 

flowchart LR
    subgraph patterns["복제 토폴로지 패턴"]
        A1["Active/Passive<br/>A->B"] 
        A2["Active/Active<br/>A->B, B->A"]
        A3["Aggregation<br/>A->K, B->K, C->K"]
        A4["Fan-out<br/>K->A, K->B, K->C"]
    end

가장 많이 쓰이는 두 패턴:

  • Active/Passive (A->B): primary에서 secondary로 단방향 복제. DR(disaster recovery) 용도. 장애 시 secondary로 전환(failover).
  • Active/Active (A->B, B->A): 양방향 복제. 두 리전 모두 생산·소비. 지연 허용 오차가 큰 워크로드.

Active/Active에서 복제 "루프"(A→B로 복제된 데이터가 다시 B→A로 복제되는 현상)는 같은 MM2 설정 파일에 두 flow를 정의하면 자동으로 방지된다. MM2가 복제된 토픽(이름에 source alias가 붙은)을 식별해 되복제하지 않기 때문.

복제된 토픽의 이름 규칙 — DefaultReplicationPolicy

MM2는 source topic을 target으로 복제할 때 이름 앞에 source cluster alias를 붙인다. 기본 DefaultReplicationPolicy에 따른 규칙: {source_alias}.{topic_name} (DefaultReplicationPolicy.java)

us-west (source)       us-east (target)
================       =================
foo-topic         -->  us-west.foo-topic
bar-topic         -->  us-west.bar-topic

이 이름 변형이 왜 필요한가 — 같은 토픽 이름을 가진 데이터가 출처가 섞이는 것을 막기 위해. Active/Active에서 foo 토픽이 양쪽에 있다면, us-west의 foo는 us-east에 us-west.foo로, us-east의 foo는 us-west에 us-east.foo로 복제된다. 루프 없이 출처가 추적 가능하다.

구분자(separator)는 기본 .이지만 변경 가능:

# 커스텀 구분자
replication.policy.separator = _
# 결과: us-west_foo-topic

완전히 다른 이름 규칙이 필요하면 replication.policy.class로 커스텀 ReplicationPolicy 구현체를 지정할 수 있다. (IdentityReplicationPolicy를 쓰면 이름 변형을 하지 않지만, Active/Active에서는 루프 위험이 있으므로 주의.)

이름 규칙이 consumer에게 영향을 준다 — target에서 소비하려면 원래 foo-topic이 아니라 us-west.foo-topic을 구독해야 한다. 이는 장애 전환(failover) 시 consumer 설정 변경이 필요하다는 의미이기도 하다.

MM2 구성 — 설정 파일 한 개로 모든 것을

MM2는 단일 설정 파일(connect-mirror-maker.properties)로 모든 복제를 정의한다. 이 파일에 cluster 정의, 복제 flow, Connect/producer/consumer 설정이 모두 들어간다.

전체 구성 예시 — Active/Passive

# Kafka 4.3, KRaft
# cluster alias 정의
clusters = primary, secondary

# 각 cluster 연결 정보
primary.bootstrap.servers = broker1-primary:9092,broker2-primary:9092
secondary.bootstrap.servers = broker1-secondary:9092,broker2-secondary:9092

# 복제 flow 활성화 (primary -> secondary 단방향)
primary->secondary.enabled = true
secondary->primary.enabled = false

# 복제할 토픽 (정규식)
primary->secondary.topics = .*

# 내부 topic 복제 팩터 (프로덕션: 3 이상 권장)
replication.factor = 3
checkpoints.topic.replication.factor = 3
heartbeats.topic.replication.factor = 3
offset-syncs.topic.replication.factor = 3

# Connect 내부 topic 복제 팩터
offset.storage.replication.factor = 3
status.storage.replication.factor = 3
config.storage.replication.factor = 3

# consumer 그룹 offset 동기화 활성화 (DR 핵심 설정)
sync.group.offsets.enabled = true
sync.group.offsets.interval.seconds = 60
emit.checkpoints.enabled = true
emit.checkpoints.interval.seconds = 60

# 복제에서 제외할 토픽 (내부 topic 제외)
topics.exclude = .*[\-\.]internal, .*\.replica, __.*

(connect-mirror-maker.properties 예시) (MirrorConnectorConfig.java)

설정 문법의 계층 구조

MM2 설정은 전역 기본값 → flow별 오버라이드 계층을 가진다:

# 전역 기본값 (모든 flow에 적용)
topics = .*
groups = .*

# flow별 오버라이드
primary->secondary.topics = foo.*, bar.*
primary->secondary.groups = important-.*

또한 Connect, producer, consumer 설정을 cluster별로 커스터마이징할 수 있다:

# source cluster consumer 설정
primary.consumer.isolation.level = read_committed

# target cluster producer 설정
secondary.producer.compression.type = gzip
secondary.producer.buffer.memory = 32768

실행

# Kafka 4.3, KRaft 단일 노드 환경
# 전체 flow 실행
bin/connect-mirror-maker.sh config/connect-mirror-maker.properties

# 특정 target만 (consume from remote, produce to local)
bin/connect-mirror-maker.sh config/connect-mirror-maker.properties --clusters secondary

--clusters 옵션은 특정 target cluster에 가까운 위치에서만 실행할 때 사용. producer가 원격 cluster로 보낼 때 발생하는 지연(producer lag)을 줄이는 공식 권장 사항이다. 

멀티 리전 offset 동기화 — 이 글의 핵심

DR 시나리오에서 가장 중요한 질문으로 돌아가자: 장애 전환 후 consumer가 어디서부터 읽어야 하는가? MM2는 이 문제를 offset 변환(translation)으로 푼다.

offset이 왜 다른가 — 복제 과정에서 발생하는 offset 불일치

source에서 offset 100인 record가 target으로 복제되면, target에서의 offset이 100이라는 보장이 없다. 이유:

  • source와 target의 파티션 수가 다를 수 있다 (MM2는 partition 수를 동기화하려 하지만, 기존 토픽이 이미 있는 경우는 다를 수 있음).
  • source에서 retention으로 일부 record가 삭제됐을 수 있다.
  • 복제 중 일부 record가 누락됐거나 재시도로 인해 순서가 다를 수 있다.

따라서 source offset 100이 target에서는 offset 97일 수도 있고 103일 수도 있다. 이 매핑을 저장하고 변환하는 것이 offset 동기화의 본질이다.

MM2의 offset 동기화 메커니즘

MM2는 offset 동기화를 두 단계로 수행한다:

flowchart TD
    subgraph 1단계["1단계: offset 매핑 기록"]
        S1["MirrorSourceConnector<br/>record 복제"] --> OST["offset-syncs topic<br/>source offset → target offset 매핑"]
    end
    subgraph 2단계["2단계: checkpoint 발행 + offset 동기화"]
        CC["MirrorCheckpointConnector<br/>source consumer 그룹 offset 읽기"] --> OST
        OST --> TR["offset 변환<br/>source offset → target offset"]
        TR --> CKPT["checkpoints topic<br/>(target에 저장)"]
        TR -->|"sync.group.offsets.enabled=true"| TCO["target __consumer_offsets<br/>(직접 기록)"]
    end

1단계 — offset-syncs topic: MirrorSourceConnector가 record를 복제할 때마다, source offset과 target offset의 매핑을 mm2-offset-syncs.{target}.internal topic에 기록한다. (MirrorConnectorConfig.java) 이 topic은 기본적으로 source cluster에 저장된다 (offset-syncs.topic.location = source). (MirrorConnectorConfig.java)

2단계 — checkpoint + group offset 동기화: MirrorCheckpointConnector가 source cluster에서 consumer 그룹의 현재 offset을 읽고, offset-syncs topic의 매핑을 이용해 target 기준 offset으로 변환한 뒤:

  1. checkpoints topic({target}.checkpoints.internal)에 변환된 offset을 기록한다 — "source 그룹 X가 source offset 100까지 읽었고, 이는 target offset 97에 해당한다."
  2. sync.group.offsets.enabled = true인 경우, 변환된 offset을 target cluster의 __consumer_offsets topic에 직접 기록한다. 이렇게 되면 target cluster로 consumer를 전환했을 때, source에서 읽던 위치부터 자연스럽게 이어서 읽을 수 있다.

(MirrorCheckpointConfig.java)에 따르면, sync.group.offsets.enabled의 기본값은 false다. 의도하지 않은 offset 덮어쓰기를 막기 위해 보수적으로 기본값이 설정된 것이다. DR 목적이라면 반드시 true로 설정해야 한다.

offset 동기화의 치명적인 전제 조건

sync.group.offsets.enabled = true가 동작하려면 "target cluster에 해당 consumer 그룹의 활성 consumer가 없어야 한다"(MirrorCheckpointConfig.java)의 문서에 명시된 전제 조건이다.

이 조건이 왜 중요한가:

  • target에 활성 consumer가 있으면, MM2가 덮어쓰는 offset과 consumer가 자체적으로 관리하는 offset이 충돌한다.
  • Active/Passive DR에서는 정상적으로 동작 — 평소 target에 consumer가 없으므로 MM2가 offset을 안전하게 동기화한다.
  • Active/Active에서는 제약이 된다 — 양쪽에 consumer가 있으므로 offset 동기화가 제대로 동작하지 않는다.

이 제약 때문에 Active/Active에서는 offset 동기화 대신 checkpoints topic을 직접 조회하여 애플리케이션 수준에서 offset을 복구하는 패턴이 필요하다. MirrorClient API(kafka-clientsorg.apache.kafka.connect.mirror.MirrorClient)를 통해 checkpoint를 조회할 수 있다.

offset lag 허용 임계값 — offset.lag.max

source offset을 target offset으로 변환할 때, 변환 데이터가 없는 offset(매핑이 아직 기록되지 않은 최신 영역)는 어떻게 처리되는가. offset.lag.max(기본값: 100) 설정이 이를 제어한다 — 매핑이 없는 offset 차이가 이 값 이하면 가장 가까운 매핑을 사용하고, 초과하면 checkpoint를 생략한다. (MirrorConnectorConfig.java)

너무 낮으면 복제 지연 시 checkpoint가 누락되고, 너무 높으면 정확도가 떨어진다. 처리량이 높은 토픽은 기본값(100)으로 충분하지만, 낮은 처리량 토픽은 조정이 필요할 수 있다.

Active/Active 구성 — 멀티 리전 양방향 복제

Active/Active는 두 리전 모두에서 읽기·쓰기를 수행하면서 데이터를 상호 복제한다.

# Kafka 4.3, KRaft
clusters = us-west, us-east

us-west.bootstrap.servers = broker1-west:9092,broker2-west:9092
us-east.bootstrap.servers = broker1-east:9092,broker2-east:9092

# 양방향 flow
us-west->us-east.enabled = true
us-east->us-west.enabled = true

# 모든 토픽 복제
topics = .*
topics.exclude = .*[\-\.]internal, .*\.replica, __.*

# 내부 topic 복제 팩터
replication.factor = 3
checkpoints.topic.replication.factor = 3
heartbeats.topic.replication.factor = 3
offset-syncs.topic.replication.factor = 3

# checkpoint 발행 (양쪽 consumer 모니터링)
emit.checkpoints.enabled = true
emit.checkpoints.interval.seconds = 60

# offset 동기화는 Active/Active에서는 제약이 있음 (위 참조)
sync.group.offsets.enabled = true
sync.group.offsets.interval.seconds = 60

Active/Active에서 루프 방지를 위해 topics.exclude를 별도로 설정할 필요는 없다 — 같은 설정 파일에 두 flow를 정의하면 MM2가 자동으로 us-west.*, us-east.* 패턴의 토픽(이미 복제된 토픽)을 되복제하지 않는다. 

Active/Active의 consumer 관점

양방향 복제 환경에서 consumer가 foo 토픽을 구독하면, 같은 cluster의 원본 foo와 반대쪽에서 복제된 us-east.foo(또는 us-west.foo) 모두를 구독해야 양쪽 데이터를 모두 받는다. 이를 위해 MM2는 consumer가 하나의 "논리적 토픽"으로 통합 구독할 수 있게 지원하지 않으므로 — 애플리케이션이 두 토픽을 모두 구독하거나, upstream에서 통합 토픽으로 다시 쓰는 별도 계층이 필요하다.

이 한계는 MM2 설계의 트레이드오프다: 단순성(이름 규칙 기반 출처 추적)을 택하는 대신 consumer 복잡성을 감수한다. 대안으로 Kafka 3.9+에서 도입된 Cluster Linking(Confluent 확장, ASF core 아님)이 이 문제를 다르게 접근하지만, 이 글의 범위를 벗어난다.

프로덕션 운영 고려사항

consume from remote, produce to local

공식 문서가 명시하는 최우선 권장 사항이다. 

First DC              Second DC
==========            =================
primary ------------- MM2 ---------> secondary
(remote / source)     (local / target)

Kafka producer는 consumer보다 불안정한 네트워크에 취약하다 (ack 대기, 재시도, 타임아웃). 따라서 MM2 프로세스를 target cluster와 같은 위치에 배치하고 --clusters 옵션으로 로컬 target만 지정하는 것이 지연 최소화의 핵심이다.

# secondary DC에서 실행 — primary(원격)에서 읽고 secondary(로컬)로 쓰기
bin/connect-mirror-maker.sh mm2.properties --clusters secondary

tasks.max 설정

MM2는 Connect 기반이므로, tasks.max로 병렬 task 수를 조절한다. 기본값은 1이며, 프로덕션에서는 최소 2 이상을 권장한다 — topic-partition 수와 하드웨어 리소스에 따라 증가.

# 각 MM2 프로세스의 최대 task 수
tasks.max = 5

내부 topic 관리

MM2는 여러 내부 topic을 생성한다. (connect-mirror-maker.properties)

topic 위치 목적 복제 팩터 설정
heartbeats target connector↔cluster 연결 상태 heartbeats.topic.replication.factor
{target}.checkpoints.internal source (기본) 변환된 offset checkpoint checkpoints.topic.replication.factor
mm2-offset-syncs.{target}.internal source (기본) source→target offset 매핑 offset-syncs.topic.replication.factor
Connect 내부 topic (*-configs, *-offsets, *-status) target Connect 프레임워크 상태 *.storage.replication.factor

프로덕션에서는 모든 내부 topic의 복제 팩터를 3 이상으로 설정해야 한다. 기본 예제 파일에서는 1로 설정되어 있으나, 이는 개발/테스트용이다.

설정 일관성 — 치명적인 함정

여러 MM2 프로세스가 같은 target cluster를 향해 복제할 때, 설정이 다르면 마지막에 실행된 프로세스의 설정으로 덮어쓰기된다.

# process 1
A->B.enabled = true
A->B.topics = foo

# process 2 (같은 target B를 향함)
A->B.enabled = true
A->B.topics = bar
# 결과: foo 또는 bar 중 하나만 복제됨 (leader에 따라 결정)

→ 모든 MM2 프로세스가 동일한 설정 파일을 사용해야 한다. 조직 수준에서 단일 설정 파일을 관리하고 자동화 도구(Ansible, Kubernetes ConfigMap 등)로 배포하는 것이 안전하다.

exactly-once 지원 (Kafka 3.5+)

dedicated MM2 cluster에 대해 exactly-once semantic이 지원된다 (Kafka 3.5.0부터).

# target cluster에 exactly-once 쓰기
secondary.exactly.once.source.support = enabled

# MM2 노드 간 내부 통신 활성화 (필수)
dedicated.mode.enable.internal.rest = true
listeners = http://localhost:8080

# source consumer에서 aborted transaction 필터링
primary.consumer.isolation.level = read_committed

기존 MM2 cluster를 exactly-once로 전환하려면 2단계 업그레이드가 필요하다: 먼저 exactly.once.source.support = preparing으로 전체 노드 재시작, 이후 enabled로 재재시작. 

모니터링 — replication-latency가 핵심 메트릭

MM2는 kafka.connect.mirror 메트릭 그룹으로 JMX 메트릭을 발행한다.

# MirrorSourceConnector 메트릭
record-count              # 복제된 record 수
record-rate               # records/sec
replication-latency-ms    # source → target 전파 지연 (핵심)
byte-rate                 # bytes/sec

# MirrorCheckpointConnector 메트릭
checkpoint-latency-ms     # consumer offset 복제 지연

replication-latency-ms는 source에서 record가 쓰인 시각과 target에 복제된 시각의 차이이다. DR 시나리오에서 이 값이 크면, 장애 전환 시 최근 데이터가 유실될 수 있음을 의미한다. Prometheus + Grafana로 replication-latency-mscheckpoint-latency-ms를 대시보드에 반드시 포함해야 한다.

console-consumer 테스트 시 주의

기본적으로 MM2는 console-consumer-.*, connect-.*, __.* 패턴의 consumer 그룹을 복제에서 제외한다 (groups.exclude 기본값). 테스트로 console consumer를 실행한 그룹의 offset이 동기화되지 않는다면 이 설정이 원인이다.

테스트 시에는 임시로 제외 목록을 수정:

# 테스트용 — console-consumer 그룹도 동기화
groups.exclude = connect-.*, __.*

테스트 완료 후 반드시 원래대로 복구.

DR 장애 전환(failover) 실제 시나리오

Active/Passive DR에서 장애 전환은 다음 순서로 수행한다:

flowchart TD
    A["1. primary 장애 감지"] --> B["2. consumer를 secondary로 전환<br/>(target 토픽명 사용: primary.foo)"]
    B --> C["3. 동기화된 offset으로 이어서 소비<br/>(sync.group.offsets=true였으므로 자동)"]
    C --> D["4. producer를 secondary로 전환"]
    D --> E["5. primary 복구 후<br/>역방향 flow로 데이터 역동기화"]

전환 시 consumer가 구독하는 토픽 이름이 바뀐다 — fooprimary.foo (DefaultReplicationPolicy). 이를 자동화하려면 consumer 설정에서 토픽 이름을 환경 변수로 관리하고, failover 시 이 값을 교체하는 메커니즘이 필요하다.

장애 복구(failback) 후 primary와 secondary 간 데이터 일관성을 맞추려면, 복구된 primary로 역방향 복제 flow를 임시 활성화해야 한다. 단, 이미 소비된 offset 이후의 데이터만 복제되도록 주의.

MM2 vs 클러스터 내 복제 — 혼동하면 안 되는 것

항목 클러스터 내 복제 (ISR/HW) 클러스터 간 복제 (MM2)
목적 단일 클러스터 내 broker 간 데이터 안전성 서로 다른 클러스터/리전 간 데이터 복제
단위 partition replica topic (데이터 + 설정 + offset + ACL)
지연 밀리초 (동기/비동기 복제) 네트워크 RTT + 복제 파이프라인 지연
offset 보존 같은 cluster이므로 동일 변환 필요 (source ≠ target offset)
장애 조치 자동 (리더 선출) 수동 또는 반자동 (consumer/producer 전환 필요)

흔히 묻는 것, 흔히 틀리는 것

오해 정정
"MM2는 데이터만 복제한다" 아니다. topic 설정, ACL, consumer offset까지 복제(단, offset 동기화는 기본 비활성)
"복제된 topic 이름이 같다" 아니다. DefaultReplicationPolicy{source_alias}.{topic}로 이름을 바꾼다
"offset 동기화가 자동으로 켜진다" 아니다. sync.group.offsets.enabled 기본값은 false. DR 목적이면 명시적 true 필요
"Active/Active에서 offset 동기화가 잘 된다" 제약이 있다. target에 활성 consumer가 없어야 동작하므로 Active/Active엔 부적합
"복제 루프를 막으려면 topics.exclude를 수동으로 설정해야" 같은 설정 파일에 두 flow를 정의하면 MM2가 자동으로 루프 방지
"MM2는 단일 프로세스가 안전하다" 같은 target을 향하는 여러 MM2 프로세스의 설정이 다르면 리더 선출에 따라 복제가 조용히 사라짐
"DR 장애 전환은 자동이다" 아니다. consumer/producer 재연결, 토픽 이름 변경, offset 검증을 포함한 런북(runbook)이 필요
"MM2로 exactly-once가 자동이다" dedicated cluster에서 exactly.once.source.support=enabled 필요(3.5+). 기본은 at-least-once

요약 — 이 글의 결론

  • MM2는 Connect 기반 크로스 클러스터 복제 프레임워크다. 데이터뿐 아니라 토픽 설정, ACL, consumer offset까지 복제한다 — 이것이 MirrorMaker 1과의 근본적 차이.
  • 복제된 토픽 이름에는 source alias가 붙는다 (us-west.foo). 이 규칙이 루프 방지와 출처 추적을 가능하게 하지만, consumer는 target에서 다른 이름으로 구독해야 한다.
  • offset 동기화는 sync.group.offsets.enabled = true로 명시적 활성화해야 한다 (기본값 false). 핵심 전제: target에 활성 consumer가 없어야 동작한다 — Active/Passive DR에는 적합, Active/Active에는 제약.
  • consume from remote, produce to local — MM2 프로세스는 target 근처에 배치한다. producer가 consumer보다 네트워크 지연에 취약하기 때문.
  • 설정 일관성이 치명적이다 — 같은 target을 향하는 모든 MM2 프로세스는 동일한 설정 파일을 써야 한다. 다르면 리더 선출에 따라 일부 복제가 조용히 사라진다.
  • DR 장애 전환은 자동이 아니다 — 토픽 이름 변경, consumer/producer 재연결, offset 검증을 포함한 런북(runbook)이 있어야 한다.

생각해 볼 문제

  1. Active/Active 환경에서 consumer가 source의 foo와 복제된 us-east.foo를 모두 구독하고 있다. 같은 record를 두 번 처리하지 않으려면 애플리케이션 수준에서 어떤 설계가 필요할까?
  2. sync.group.offsets.enabled = true인데 DR 전환 후 consumer가 offset 0부터 다시 읽는다면, 어떤 원인을 의심해야 할까?
  3. 세 개의 리전(west, east, north)이 있고 각 리전에 두 개의 클러스터가 있다. XDCR(Cross Data Center Replication)을 포함한 전체 복제 토폴로지에서 --clusters 옵션 없이 실행하면 어떤 문제가 발생할까?
  4. MM2의 exactly-once가 활성화된 환경에서 source cluster의 producer가 transaction을 abort했다. target에서 이 abort된 데이터가 어떻게 처리되는가?
  5. offset-syncs.topic.locationsource에서 target으로 변경하면 어떤 장단점이 있을까?

참고

'Data & Platform > Event Streaming' 카테고리의 다른 글

Kafka - 12. operations  (0) 2026.07.09
Kafka - 11. kafka streams  (0) 2026.07.09
Kafka - 10. kafka connect  (0) 2026.07.09
Kafka - 09. schema registry  (1) 2026.07.09
Kafka - 08. delivery semantics  (0) 2026.07.09