Multi-Cluster Strategy & MirrorMaker 2.0: Membangun Arsitektur Lintas Wilayah #

Ketika sistem yang kita bangun tumbuh menjadi fondasi utama operasi bisnis perusahaan, mengandalkan satu kluster Apache Kafka tunggal di satu pusat data (data center) menjadi sebuah risiko besar. Bencana alam, kegagalan jaringan regional pada penyedia cloud, atau mati totalnya listrik di pusat data dapat melumpuhkan seluruh aplikasi produser dan konsumen kita seketika. Untuk menjamin kelangsungan bisnis (business continuity), kita harus melangkah ke tingkat berikutnya: merancang arsitektur multi-kluster yang tersebar di berbagai wilayah geografis yang berbeda.

Membangun arsitektur multi-kluster di Apache Kafka tidak semudah melakukan replikasi database relasional biasa. Karakteristik Kafka yang mengandalkan throughput tinggi dan konsumsi data berbasis offset menuntut kita untuk memahami secara mendalam bagaimana data disinkronkan, bagaimana offset konsumen dialihkan saat terjadi bencana, dan bagaimana mencegah terjadinya loop replikasi tanpa akhir. Dalam panduan ini, kita akan membedah berbagai strategi multi-kluster, arsitektur MirrorMaker 2.0, konfigurasi operasional, translasi offset konsumen, serta strategi pemulihan bencana (Disaster Recovery Failover).

Kebutuhan Strategi Multi-Kluster di Produksi #

Sebelum kita meninjau aspek teknikal, mari kita petakan skenario bisnis dan operasional utama yang mendasari kebutuhan organisasi kita untuk menggunakan lebih dari satu kluster Kafka:

1. Pemulihan Bencana (Disaster Recovery - DR) #

Ini adalah alasan paling umum. Jika kluster utama kita di Region Jakarta (Primary) mengalami mati total, kita harus memiliki kluster cadangan di Region Singapura (Disaster Recovery) yang siap menggantikan peran kluster utama dengan kehilangan data minimal (RPO rendah) dan waktu pemulihan sesingkat mungkin (RTO rendah).

2. Lokalisasi Data dan Kepatuhan Regulasi (Data Localization & Compliance) #

Banyak yurisdiksi hukum menetapkan bahwa data pribadi warga negara tidak boleh keluar dari batas wilayah negara tersebut. Dengan strategi multi-kluster, kita dapat mengoperasikan kluster lokal di setiap negara untuk menangani data sensitif secara lokal, lalu mengirimkan data yang sudah diagregasi atau disamarkan (masked) ke kluster pusat di kantor pusat.

3. Edge-to-Cloud Ingestion (Hub-and-Spoke) #

Pada arsitektur IoT atau retail modern, kita mungkin memiliki ribuan perangkat edge (seperti gerai toko fisik atau menara telekomunikasi) yang masing-masing menjalankan kluster Kafka kecil untuk menjamin operasi offline. Data dari kluster-kluster edge ini kemudian disinkronkan secara asinkron ke kluster cloud pusat raksasa untuk pemrosesan analitik batch.

4. Mengurangi Latensi Pengguna (User Latency Optimization) #

Menaruh seluruh broker Kafka di satu benua akan memperlambat waktu respon bagi pengguna yang berada di belahan dunia lain. Dengan menempatkan kluster di dekat pengguna (misalnya, satu di Amerika Serikat, satu di Eropa, dan satu di Asia), aplikasi produser lokal dapat menulis data dengan latensi sangat rendah, sementara sinkronisasi antar wilayah diselesaikan di latar belakang melalui pipa replikasi asinkron.


Topologi Replikasi Multi-Kluster #

Terdapat tiga pola topologi logis utama untuk menghubungkan kluster-kluster Kafka kita secara geografis. Masing-masing memiliki keseimbangan (trade-off) tersendiri antara kompleksitas operasional dan ketahanan sistem.

1. Topologi Active-Passive (DR Hot Standby) #

Dalam topologi ini, seluruh aplikasi produser dan konsumen hanya menulis dan membaca dari satu kluster utama (Active Cluster). Sementara itu, kluster cadangan (Passive Cluster) hanya menerima data hasil replikasi dari kluster utama di latar belakang.

flowchart TB
    subgraph Active ["Kluster Active (Jakarta)"]
        direction BT
        Produser["Produser"] --> |"Tulis"| ClusterA["Kluster Active"]
        Consumer["Konsumen"] --> |"Baca"| ClusterA
    end
    
    subgraph Passive ["Kluster Passive (Singapura)"]
        direction BT
        Backup["(Cadangan)"] -. "Tidur" .-> ClusterB["Kluster Passive"]
    end
    
    ClusterA -- "Replikasi (Asinkron)" --> ClusterB
  • RPO (Recovery Point Objective): Sangat rendah (bergantung pada lag replikasi asinkron, biasanya di bawah beberapa detik).
  • RTO (Recovery Time Objective): Sedikit lambat karena membutuhkan proses pengalihan (switchover) aplikasi klien secara manual atau otomatis via perubahan DNS.
  • Keunggulan: Sederhana, tidak ada resiko tabrakan data (write conflicts), dan konsistensi data mudah dijaga.

2. Topologi Active-Active (Dual Ingest & Cross-Replication) #

Dalam model ini, kedua kluster aktif secara bersamaan. Produser lokal di wilayah A menulis ke kluster A, dan produser lokal di wilayah B menulis ke kluster B. Kedua kluster saling mereplikasi data satu sama lain secara dua arah (bidirectional).

flowchart TD
    subgraph ClusterA ["Kluster A (Jakarta)"]
        direction BT
        ProdA["Produser A"] --> |"Tulis"| CA["Kluster A"]
        ConsA["Konsumen A"] <--- |"Baca"| CA
    end
    
    subgraph ClusterB ["Kluster B (Singapura)"]
        direction BT
        ProdB["Produser B"] --> |"Tulis"| CB["Kluster B"]
        ConsB["Konsumen B"] <--- |"Baca"| CB
    end
    
    CA -- "Replikasi A ke B" --> CB
    CB -- "Replikasi B ke A" --> CA
  • Keunggulan: Memanfaatkan resource server secara maksimal di kedua wilayah dan memberikan latensi tulis lokal yang sangat rendah bagi pengguna global.
  • Kekurangan: Sangat kompleks. Kita berisiko mengalami loop replikasi tanpa akhir (di mana data dari A direplikasi ke B, lalu direplikasi kembali dari B ke A sebagai data baru). Selain itu, pengurutan event (event ordering) secara global tidak dapat dijamin karena latensi jaringan antar wilayah bersifat fluktuatif.

3. Topologi Hub-and-Spoke (Agregasi Data) #

Topologi ini menggunakan banyak kluster satelit (Spoke) yang bertugas mengumpulkan data secara lokal, kemudian mereplikasi seluruh data tersebut ke satu kluster pusat (Hub) untuk kebutuhan konsolidasi data, data warehousing, atau analitik AI berskala besar.

flowchart TD
    A["Kluster A (Store 01)"] -- "Replikasi" --> Center["Kluster Pusat (Headquarters)"]
    B["Kluster B (Store 02)"] -- "Replikasi" --> Center
  • Keunggulan: Mengurangi beban jaringan WAN karena kluster lokal bertindak sebagai buffer. Jika koneksi WAN ke pusat terputus, toko lokal tetap beroperasi normal dan menyinkronkan data kembali setelah koneksi pulih.
  • Kekurangan: Kluster pusat harus dirancang dengan kapasitas penyimpanan dan throughput yang sangat besar untuk menampung agregasi seluruh kluster satelit.

Replikasi Data Menggunakan MirrorMaker 2.0 (MM2) #

Untuk mewujudkan topologi multi-kluster di atas, Apache Kafka menyediakan kakas (tool) replikasi bawaan yang tangguh bernama MirrorMaker 2.0 (MM2).

Arsitektur Internal MirrorMaker 2.0 #

MirrorMaker 1.0 (versi lama) hanyalah konsumen dan produser sederhana yang dibungkus bersama, yang sering kali kehilangan data, tidak mereplikasi konfigurasi topik, dan mudah mengalami bottleneck. MirrorMaker 2.0 mengatasi masalah ini dengan dibangun sepenuhnya di atas kerangka kerja Kafka Connect.

MM2 terdiri dari beberapa connector internal yang bekerja secara sinergis:

  1. MirrorSourceConnector: Membaca data dari topik di kluster asal (source) dan menulisnya ke kluster tujuan (target). Connector ini juga bertugas mereplikasi konfigurasi topik (seperti jumlah partisi dan konfigurasi retensi).
  2. MirrorCheckpointConnector: Bertugas memetakan offset konsumen dari kluster asal ke kluster tujuan secara periodik. Ini sangat krusial untuk proses failover aplikasi konsumen.
  3. MirrorHeartbeatConnector: Mengirim pesan detak jantung secara periodik ke kluster tujuan untuk memverifikasi bahwa jalur konektivitas antar kluster berjalan aktif.

Pencegahan Loop Replikasi Lintas Kluster #

Bagaimana MM2 mencegah terjadinya loop tanpa akhir pada topologi Active-Active? MM2 memperkenalkan konsep penamaan namespace topik secara dinamis.

Secara default, saat MM2 mereplikasi topik bernama orders dari kluster bernama jakarta ke kluster singapura, topik tersebut akan ditulis di kluster singapura dengan nama jakarta.orders. Jika ada MM2 lain yang mereplikasi balik dari singapura ke jakarta, MM2 akan melihat prefix jakarta. pada nama topik tersebut dan secara cerdas menolak untuk mereplikasinya kembali karena mengetahui bahwa data tersebut berasal dari kluster jakarta itu sendiri.

Contoh Konfigurasi MirrorMaker 2.0 di Produksi #

MM2 dapat dijalankan dalam tiga mode: Dedicated (menjalankan kluster Connect mandiri khusus MM2), Connect Cluster (dideploy sebagai connector biasa di kluster Kafka Connect yang sudah ada), atau Legacy (menggunakan script pembungkus). Cara paling stabil untuk produksi adalah menggunakan Dedicated Mode.

Berikut adalah contoh berkas konfigurasi mm2.properties lengkap untuk mereplikasi data dari kluster jakarta (Primary/Source) ke kluster singapura (Backup/Target) dengan topologi Active-Passive:

# Mendefinisikan nama alias untuk kluster kita
clusters = jakarta, singapura

# Konfigurasi koneksi untuk masing-masing kluster
jakarta.bootstrap.servers = broker-jkt-1:9092,broker-jkt-2:9092,broker-jkt-3:9092
singapura.bootstrap.servers = broker-sg-1:9092,broker-sg-2:9092,broker-sg-3:9092

# Mengonfigurasi arah replikasi (dari jakarta -> singapura)
jakarta->singapura.enabled = true

# Menentukan pola nama topik yang ingin direplikasi
# Kita menggunakan regex untuk mereplikasi semua topik kecuali topik internal system
jakarta->singapura.topics = .*
jakarta->singapura.topics.blacklist = _.*, .*\.internal, __consumer_offsets

# Mengaktifkan sinkronisasi grup konsumen dan offset
jakarta->singapura.emit.checkpoints.enabled = true
jakarta->singapura.sync.group.offsets.enabled = true
jakarta->singapura.sync.group.offsets.interval.seconds = 5

# Detak jantung untuk pemantauan konektivitas
jakarta->singapura.emit.heartbeats.enabled = true
jakarta->singapura.emit.heartbeats.interval.seconds = 1

# Menentukan apakah ingin menggunakan prefix nama kluster pada topik tujuan
# Untuk Active-Passive murni, kita bisa mematikan prefix agar nama topik tetap sama
# WARNING: Jangan matikan ini jika kita menggunakan topologi Active-Active!
jakarta->singapura.rename.topics = false

# Parameter performa internal Kafka Connect untuk MM2
tasks.max = 8
jakarta.consumer.auto.offset.reset = earliest
singapura.producer.acks = all
singapura.producer.max.in.flight.requests.per.connection = 1
singapura.producer.compression.type = zstd

Untuk menjalankan MirrorMaker 2.0 di latar belakang menggunakan berkas konfigurasi tersebut, gunakan perintah terminal berikut:

# Jalankan MM2 daemon di server khusus Connect kita
connect-mirror-maker.sh /etc/kafka/mm2.properties > /var/log/kafka/mm2.log 2>&1 &

Mekanisme Sinkronisasi Offset dan Failover Konsumen #

Tantangan terbesar dalam disaster recovery multi-kluster adalah bagaimana memindahkan aplikasi konsumen kita dari kluster utama ke kluster cadangan tanpa membaca ulang data dari awal (duplicate processing) atau melewatkan data yang belum dibaca (data loss).

Mengapa Offset Tidak Bisa Direplikasi Mentah-Mentah? #

Offset di Kafka bersifat lokal untuk setiap partisi di dalam satu kluster tertentu. Karena adanya perbedaan waktu pembuatan topik, pemadatan log (log compaction), atau kegagalan broker saat penulisan, offset ke-1000 di kluster jakarta tidak pernah dijamin berisi pesan yang persis sama dengan offset ke-1000 di kluster singapura.

Oleh karena itu, mereplikasi angka offset mentah-mentah dari __consumer_offsets secara langsung akan merusak posisi baca konsumen setelah failover.

Solusi: Penerjemahan Offset (Offset Translation) via Checkpoint #

MirrorMaker 2.0 memecahkan masalah ini dengan menulis metadatar pemetaan offset secara periodik ke topik internal bernama singapura.checkpoints.internal di kluster target. Topik ini berisi informasi seperti:

  • Nama grup konsumen.
  • Nama topik dan nomor partisi.
  • Offset asal (source offset).
  • Offset tujuan hasil terjemahan (translated target offset).
  • Metadata waktu (timestamp).

Ketika aplikasi konsumen dialihkan ke kluster singapura, library konsumen atau alat bantu failover kita akan membaca metadata checkpoint ini untuk mengetahui posisi offset yang setara di kluster baru, lalu melakukan operasi seek() sebelum mulai membaca pesan baru.


Alur Replikasi Data dan Failover Lintas Wilayah #

Berikut adalah visualisasi alur bagaimana data direplikasi dari wilayah aktif ke wilayah pasif, dan bagaimana aplikasi klien dialihkan ketika terjadi insiden pemadaman total di wilayah aktif:

flowchart TD
    subgraph Region_Aktif ["WILAYAH AKTIF (PRIMARY - JAKARTA)"]
        direction TB
        ProdA["Aplikasi Produser A"]
        ClientG["Aplikasi Konsumen B"]
        ClusterA["Kluster Kafka Utama"]
        ProdA -->|1. Kirim Data| ClusterA
        ClientG -->|2. Konsumsi Data| ClusterA
    end

    subgraph Replicator_Layer ["PIPA REPLIKASI LANTAI TENGAH"]
        direction TB
        MM2["MirrorMaker 2.0 (Kafka Connect)"]
    end

    subgraph Region_Pasif ["WILAYAH PASIF (DR - SINGAPURA)"]
        direction TB
        ClusterB["Kluster Kafka Cadangan"]
        CheckpointTopic["Topik Checkpoint Internal"]
    end

    %% Alur Replikasi Utama
    ClusterA -->|"3. Pull Data & Checkpoint"| MM2
    MM2 -->|"4. Push Data & Translasikan Offset"| ClusterB
    MM2 -. "5. Tulis Metadata Checkpoint" .-> CheckpointTopic

    %% Alur Failover saat Bencana
    Region_Aktif -.->|"6. Bencana Terjadi (Mati Total)"| FailoverEvent{"DISASTER FAILOVER"}
    FailoverEvent -->|"7. Alihkan DNS / Koneksi"| ProdA_Backup["Aplikasi Produser A (Singapura)"]
    FailoverEvent -->|"8. Ambil Offset Terjemahan"| ClientG_Backup["Aplikasi Konsumen B (Singapura)"]
    
    ProdA_Backup -->|9. Tulis Data Baru| ClusterB
    CheckpointTopic -.->|"10. Baca Posisi Offset"| ClientG_Backup
    ClientG_Backup -->|11. Konsumsi Tanpa Duplikasi| ClusterB

    style FailoverEvent stroke:#d32f2f,stroke-width:3px

Strategi Mitigasi Bencana & Failover DNS #

Untuk melakukan pengalihan kluster secara mulus saat terjadi bencana (Disaster Recovery Switchover), kita harus menyusun strategi mitigasi di tingkat aplikasi dan infrastruktur jaringan.

1. Strategi Client Routing Menggunakan DNS Failover #

Kita tidak boleh menulis alamat IP fisik broker secara keras (hardcode) di dalam kode aplikasi produser atau konsumen. Alih-alih menulis broker-jkt-1:9092, gunakan nama domain DNS internal (CNAME) yang dikelola oleh load balancer atau DNS server dinamis (seperti Route 53 atau Consul):

  • kafka-bootstrap.company.internal

Saat kluster Jakarta mati total, tim SRE kita cukup mengubah arah CNAME kafka-bootstrap.company.internal untuk menunjuk ke alamat bootstrap kluster Singapura (broker-sg-1:9092). Ketika aplikasi klien mengalami putus koneksi TCP, mereka akan melakukan resolusi ulang DNS secara otomatis dan terhubung ke kluster cadangan tanpa perlu melakukan restart pod aplikasi.

Perhatikan setelan DNS TTL (Time to Live) pada OS dan JVM aplikasi kita. Jika JVM disetel untuk melakukan cache resolusi DNS selamanya (networkaddress.cache.ttl=-1), aplikasi kita tidak akan pernah mendeteksi perubahan alamat DNS failover tersebut sebelum pod di-restart secara manual. Setel nilai ini ke maksimal 10 detik di berkas konfigurasi keamanan Java (java.security).

2. Strategi Pengalihan Produser (Producer Switchover) #

Untuk mencegah hilangnya pesan saat terjadi failover, produser harus dikonfigurasi dengan toleransi tinggi terhadap putus koneksi sementara:

  • retries: Setel ke nilai maksimal (Integer.MAX_VALUE).
  • delivery.timeout.ms: Setel ke durasi yang cukup panjang (misalnya 120000 atau 2 menit) untuk memberikan waktu bagi tim SRE menyelesaikan failover DNS tanpa memicu kegagalan pengiriman pesan di sisi aplikasi.
  • acks: Wajib disetel ke all agar data benar-benar tersimpan dengan aman sebelum perpindahan dilakukan.

3. Strategi Pengalihan Konsumen (Consumer Switchover) #

Saat beralih ke kluster cadangan, konsumen harus melacak posisi offset terakhir yang berhasil diproses. Jika kita menggunakan MM2 dengan sync.group.offsets.enabled=true, MM2 akan secara otomatis menyinkronkan grup konsumen kita di kluster cadangan.

Namun, karena penyelarasan offset terjadi secara periodik (asinkron), ada kemungkinan konsumen akan membaca ulang beberapa pesan terakhir yang telah diproses sesaat sebelum pemadaman terjadi. Oleh karena itu, aplikasi konsumen kita wajib bersifat idempotens (Idempotent Consumer) agar dapat menangani pemrosesan data ganda tanpa merusak integritas database operasional kita.


Alternatif Teknologi Replikasi Selain MirrorMaker 2.0 #

Meskipun MM2 merupakan standar bawaan open source yang sangat andal, terdapat beberapa teknologi alternatif di industri yang menawarkan keunggulan spesifik:

1. Confluent Replicator #

Kakas komersial berpemilik (proprietary) dari Confluent yang terintegrasi erat dengan ekosistem mereka.

  • Keunggulan: Replicator mendukung replikasi data Schema Registry secara otomatis dan dinamis lintas wilayah, serta mampu mereplikasi ACL (Access Control Lists) secara instan.
  • Kekurangan: Membutuhkan lisensi komersial (Enterprise).

2. Uber uReplicator #

Proyek open source yang dikembangkan oleh Uber untuk mengatasi keterbatasan MirrorMaker 1.0 pada kluster berskala raksasa sebelum MM2 dirilis.

  • Keunggulan: Menggunakan Apache Helix untuk membagi tugas replikasi secara dinamis dan memiliki manajemen rebalance tugas yang sangat stabil pada throughput jutaan pesan per detik.
  • Kekurangan: Lebih kompleks untuk dideploy dan sebagian besar fiturnya kini telah diadopsi dengan baik oleh MM2.

Checklist Audit Kesiapan Disaster Recovery Multi-Kluster #

Lakukan langkah audit operasional berikut secara berkala untuk menjamin kluster cadangan kita benar-benar siap menghadapi bencana di dunia nyata:

No Item Audit Kesiapan Multi-Kluster Metode Verifikasi Status
1 Verifikasi Lag Replikasi MM2 Pantau metrik replication-latency-ms pada JMX MirrorMaker. Pastikan lag replikasi data rata-rata berada di bawah batas toleransi bisnis (misalnya < 5 detik). [ ]
2 Validasi Cache TTL DNS JVM Periksa parameter networkaddress.cache.ttl di seluruh container JVM aplikasi klien. Pastikan disetel ke nilai rendah (10-30 detik) dan bukan selamanya. [ ]
3 Pengujian Idempotensi Konsumen Lakukan simulasi pemrosesan ulang pesan lama (simulasi duplikasi offset) di lingkungan staging untuk memastikan tidak ada data ganda di database. [ ]
4 Sinkronisasi Skema Data Pastikan Schema Registry di kluster target memiliki seluruh skema yang cocok dengan kluster sumber. Terapkan replikasi skema dua arah jika diperlukan. [ ]
5 Simulasi Pemadaman Rutin (Chaos Game) Lakukan uji coba pemadaman kluster utama secara berkala di staging (Game Day) untuk melatih kesiapan tim operasional dalam menghadapi kegagalan nyata. [ ]
6 Kapasitas Penyimpanan Target Verifikasi bahwa kapasitas disk dan performa I/O di kluster cadangan setara dengan kluster utama agar tidak terjadi kelambatan performa pasca failover. [ ]

Ringkasan #

  • Pilih Topologi yang Sesuai — Gunakan Active-Passive untuk konsistensi data yang aman dan kemudahan operasional. Gunakan Active-Active hanya jika organisasi memiliki kebutuhan latensi tulis lokal global yang kritis dan siap mengelola konflik data.
  • Gunakan MirrorMaker 2.0 Dedicated — Jalankan MM2 di atas kluster Kafka Connect terdedikasi untuk skalabilitas tugas replikasi yang stabil dan toleran terhadap kegagalan.
  • Terapkan CNAME untuk Failover — Hindari hardcoding IP broker. Gunakan domain DNS internal dengan TTL rendah untuk mempercepat proses pengalihan koneksi klien secara transparan.
  • Jamin Idempotensi Aplikasi — Antisipasi duplikasi data minor pasca failover akibat lag sinkronisasi offset asinkron dengan membuat logika konsumen kita bersifat idempotent.
  • Gunakan Checkpoint untuk Transisi — Andalkan MirrorMaker Checkpoint Connector untuk melacak pemetaan offset lintas kluster secara dinamis daripada menyalin nomor offset secara mentah.

← Sebelumnya: Centralized vs Decentralized Clusters   Berikutnya: Anti-Pattern di Produksi & Checklist Kesiapan →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact