Veri Bilimi Okulu

Kafka Producer Güvenilirliği: Acks, Retry ve Idempotent Producer İlişkisini Öğrenelim
Kafka Producer Güvenilirliği: Acks, Retry ve Idempotent Producer İlişkisini Öğrenelim
kafka_safe_producer

Loading

Merhaba! Bugün Apache Kafka’nın en kritik konularından biri olan Kafka Producer güvenilirliği (producer reliability) üzerine derinlemesine bir yazı hazırladım. Eğer Kafka kullanıyorsanız veya kullanmayı planlıyorsanız, mesajlarınızın kaybolmaması ve duplicate (tekrar eden) mesajlardan kaçınmanız için bu konuyu çok iyi anlamanız gerekiyor. Hadi birlikte öğrenelim!

Producer Acks Nedir ve Neden Önemlidir?

Öncelikle acks (acknowledgment) parametresinden başlayalım. Bu parametre, Producer’ın bir mesajı gönderdiğinde “tamam, mesajın ulaştı” onayını kimlerden bekleyeceğini belirler. Üç farklı değer alabilir:

  • acks=0: Producer hiçbir onay beklemez. Mesajı gönderir ve işini bitirmiş sayar. En hızlı yöntem ama en riskli.
  • acks=1: Producer sadece leader broker’dan onay bekler. Mesaj leader’a yazıldığında onay gelir.
  • acks=all (veya -1): Producer, leader ve tüm ISR (In-Sync Replica) broker’lardan onay bekler. En güvenli ama en yavaş yöntem.

Kafka 3.0 öncesinde varsayılan değer acks=1 iken, Kafka 3.0 ve sonrasında varsayılan değer acks=all olarak değişti [1]. Bu değişiklik, Kafka’nın veri güvenilirliğine verdiği önemi gösteriyor. Yani artık yeni versiyonlarda güvenlik varsayılan olarak geliyor!

Replication Factor ve Min In-Sync Replicas İlişkisi

Şimdi replication.factor ve min.insync.replicas kavramlarını görelim. Bu iki parametre birlikte çalışarak verilerinizin ne kadar güvenli olacağını belirler.

Replication Factor (çoğaltma faktörü), bir partition’ın kaç farklı broker’da kopyasının bulunacağını söyler. Eğer replication.factor=3 ise, her partition 3 farklı broker’da saklanır: 1 leader ve 2 follower [2].

Min In-Sync Replicas (ISR) ise, bir yazma işleminin başarılı sayılması için kaç replica’nın senkronize olması gerektiğini belirler. min.insync.replicas=2 ayarı, leader dahil en az 2 replica’nın mesajı alması gerektiği anlamına gelir [3].

Durability ve Availability Dengesi

Şimdi popüler bir konfigürasyonu inceleyelim:

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

Durability (Dayanıklılık): Bu konfigürasyonla her mesajınız en az 2 broker’a yazılır. Yani bir broker çökse bile verileriniz güvende. Ancak dikkat! Eğer 2 broker birden çökerse ve sadece 1 replica kalırsa, o verilere hala okuma yapabilirsiniz ama yeni yazma işlemleri yapılamaz (çünkü min.insync.replicas=2 koşulunu sağlayamazsınız).

Availability (Erişilebilirlik): Topic’inizin yazma işlemlerine devam edebilmesi için en az 2 ISR’ın ayakta olması gerekir. Bu durumda maksimum 1 broker’ın çökmesine izin verebilirsiniz. Eğer 2 broker birden çökerse, min.insync.replicas şartını sağlayamayacağınız için yazma işlemleri NotEnoughReplicasException hatası verecektir [4].

Burada önemli bir nokta: Replication factor 3 olsa bile, min.insync.replicas 2 olduğu için sadece 1 broker kaybına dayanıklıyız. Çünkü 2 broker çökerse geriye kalan 1 broker min.insync şartını karşılayamaz. Bu yüzden durability ile availability arasında bir trade-off (denge) yapıyoruz.

Producer Retry Mekanizması

Producer’lar mesaj gönderirken hata alabilirler. İyi haber şu ki, Kafka bu durumlar için otomatik retry (yeniden deneme) mekanizması sunuyor. Geçici hatalar (transient errors) durumunda Producer mesajı tekrar göndermeye çalışır [5].

Retry Parametreleri

retry.backoff.ms: İki deneme arasındaki bekleme süresi. Varsayılan değeri 100ms’dir. Bu sayede broker’lar nefes alma fırsatı bulur ve sistem aşırı yüklenmez [6].

delivery.timeout.ms: Producer’ın bir mesajı göndermeye çalışacağı maksimum süre. Varsayılan değeri 120.000ms (120 saniye = 2 dakika). Bu süre içinde başarılı olamayan mesajlar terk edilir ve Producer’a hata döner [7].

Önemli bir nokta: Kafka’nın eski versiyonlarında retries parametresi vardı ve sayısal bir değer alırdı (örneğin retries=10). Ancak artık delivery.timeout.ms daha önemli hale geldi. Producer, bu timeout süresi dolana kadar denemeye devam eder, kaç kez denediği değil toplam süre önemlidir.

Yani şöyle düşünebilirsiniz: “2 dakika içinde ne kadar çok denersen dene, ama 2 dakika sonra pes et!” mantığı.

Mesaj Sırası ve Duplicate Mesaj Problemi

İşte burada işler karmaşıklaşıyor! Producer retry yaparken iki büyük sorunla karşılaşabiliriz:

1. Sıra Bozulması (Out-of-Order Messages)

Producer aynı anda birden fazla mesaj gönderebilir (pipelining). Bu max.in.flight.requests.per.connection parametresiyle kontrol edilir. Varsayılan değeri 5’tir [8].

Şu senaryoyu düşünelim:

  • Producer mesaj-1 ve mesaj-2’yi gönderir
  • Mesaj-1 başarısız olur ve retry’a girer
  • Mesaj-2 başarılı olur ve Kafka’ya yazılır
  • Sonra mesaj-1 tekrar gönderilir ve başarılı olur
  • Sonuç: Mesajlar 2, 1 sırasıyla saklanır!

Eğer mesajlarınız key’li ise (örneğin aynı kullanıcının işlemlerinin sıralı olması gerekiyorsa), bu büyük bir problem oluşturabilir. Mesajlarınızın sırasının bozulması, downstream (akış aşağısındaki) uygulamalarınızda hatalara yol açabilir.

Peki bu problemi nasıl çözeriz?

İşte burada max.in.flight.requests.per.connection parametresinin değeri önemli hale gelir. Bu parametreyi 1 yaparsanız, sıra bozulması problemi tamamen ortadan kalkar [8]. Çünkü Producer bir seferde sadece 1 mesaj gönderir ve onayını bekler. Ancak bu performansı ciddi şekilde düşürür.

Neyse ki Idempotent Producer kullandığınızda, Kafka daha akıllı bir çözüm sunar! Idempotent Producer aktifken max.in.flight.requests.per.connection değeri 5’e kadar olabilir ve yine de mesaj sırası korunur [9].

Nasıl mı? Idempotent Producer her mesaja sequence number eklediği için, Kafka broker’ı bu sequence number’lara bakarak mesajları doğru sıraya koyabilir. Yani mesaj-2 önce gelse bile, sequence number’dan mesaj-1’in önce olması gerektiğini anlar ve sırayı korur.

Özetle:

  • Idempotent Producer KAPALI + max.in.flight > 1: Sıra bozulması riski var!
  • Idempotent Producer KAPALI + max.in.flight = 1: Sıra korunur ama performans düşer
  • Idempotent Producer AÇIK + max.in.flight ≤ 5: Hem sıra korunur hem performans iyi! (En ideal seçenek)

Bu yüzden Kafka 3.0+ versiyonlarında hem idempotence varsayılan olarak açık hem de max.in.flight.requests.per.connection=5 olarak ayarlı. Böylece hem güvenlik hem performans sağlanıyor.ilir. Mesajlarınızın sırasının bozulması, downstream (akış aşağısındaki) uygulamalarınızda hatalara yol açabilir.

2. Duplicate Mesajlar (Mesaj Tekrarı)

Bu daha sinsi bir problem! Şöyle bir durum olabilir:

  • Producer mesajı gönderir
  • Broker mesajı alır ve disk’e yazar
  • Ancak ack (onay) Producer’a ulaşmadan network sorunu oluşur
  • Producer timeout olur ve “mesaj ulaşmadı” sanarak mesajı tekrar gönderir
  • Sonuç: Aynı mesaj iki kez kaydedilir!

Bu problemi çözmek için Idempotent Producer devreye girer.

Idempotent Producer: Büyülü Çözüm!

Kafka 0.11 versiyonuyla birlikte gelen Idempotent Producer (idempotent: aynı işlemi birden fazla yapmanın bir kez yapmakla aynı sonucu vermesi), duplicate mesaj problemini çözer [9]. Bu gerçekten harika bir özellik!

Nasıl Çalışır?

Idempotent Producer aktif olduğunda:

  1. Her Producer’a unique bir Producer ID (PID) atanır
  2. Her mesaja bir sequence number eklenir
  3. Broker, aynı PID ve sequence number’a sahip mesajı ikinci kez aldığında, mesajı tekrar yazmaz ama yine de ack gönderir

Bu sayede Producer tekrar gönderim yapsa bile, Kafka aynı mesajı sadece bir kez saklar. Hem Producer mutlu (ack aldı), hem broker mutlu (duplicate’ı engelledi), hem de verileriniz temiz!

Peki bu sequence number mekanizması nasıl çalışıyor? Kafka her partition için Producer’dan gelen mesajların sequence number’larını takip eder. Eğer bir mesaj daha önce işlenmişse (aynı sequence number), Kafka bunu anlar ve mesajı yeniden yazmaz ama Producer’a “tamam, aldım” der. Böylece Producer’ın perspective’inden (bakış açısından) her şey normal görünür.

Idempotent Producer Konfigürasyonu

Idempotent Producer’ı aktif etmek için şu ayarları yapmanız gerekir:

producerProps.put("enable.idempotence", true);
producerProps.put("acks", "all");
producerProps.put("retries", Integer.MAX_VALUE);

Ancak müjde! Kafka 3.0 ve sonrasında enable.idempotence=true varsayılan olarak aktiftir [10]. Yani artık manuel olarak açmanıza gerek yok! Bu da Kafka’nın güvenli varsayılanlar (safe defaults) felsefesine geçişinin bir parçası.

Idempotent Producer açıldığında bazı parametreler otomatik olarak ayarlanır:

  • acks=all (veya -1) – En güvenli mod
  • retries > 0 (genellikle Integer.MAX_VALUE) – Sürekli deneme
  • max.in.flight.requests.per.connection <= 5 – Sıra korunması için

Topic Level Ayarlar

Idempotent Producer’ın düzgün çalışması için sadece Producer seviyesinde ayar yapmak yetmez. Topic seviyesinde de min.insync.replicas=2 ayarının yapılması önerilir [3]. Bu sayede:

  • Mesajlar en az 2 replica’ya yazılır
  • Duplicate’lar engellenirken veri kaybı da önlenir
  • Sistem hem idempotent hem de dayanıklı olur

Safe Producer: Güvenli Yapılandırmanın Bedeli

Tüm bu güvenlik önlemleri harika, ama bedeli var mı? Evet, var! İşte Safe Producer (güvenli producer) kullanmanın maliyetleri:

1. Performans (Throughput)

acks=all kullandığınızda, Producer tüm ISR’lardan onay bekler. Bu, acks=1‘e göre daha yavaştır. Özellikle coğrafi olarak dağıtık bir Kafka cluster’ınız varsa, network latency (gecikme) artabilir.

2. Latency (Gecikme)

Her mesaj için daha fazla bekleme süresi demek, end-to-end latency’nin artması demektir. Eğer real-time (gerçek zamanlı) bir uygulama yapıyorsanız, bu konuyu göz önünde bulundurmalısınız.

3. Broker Yükü

Idempotent Producer, broker’ların her mesaj için sequence number kontrolü yapmasını gerektirir. Bu ekstra CPU ve memory kullanımı demektir. Ancak modern Kafka versiyonlarında bu maliyet optimize edilmiştir.

4. Availability Trade-off

min.insync.replicas=2 ayarı, en az 2 broker’ın ayakta olmasını gerektirir. Eğer çok sayıda broker çökerse, yazma işlemleri durabilir. Bu durumda availability azalır ama durability artar.

Peki bu maliyetlere değer mi? Kesinlikle evet! Özellikle finansal işlemler, sipariş sistemleri, log aggregation gibi kritik uygulamalarda veri kaybı ve duplicate mesajlar çok daha büyük problemlere yol açar. Biraz performans kaybı kabul edilebilir bir trade-off’tur.

Idempotent Producer vs Safe Producer

Idempotent Producer ve Safe Producer aynı şey DEĞİL, ama Safe Producer’ın bir parçası Idempotent Producer’dır.

Idempotent Producer

Sadece duplicate mesajları önlemeye odaklanan bir özelliktir. Yani:

enable.idempotence=true

Bu ayar açıldığında Producer her mesaja sequence number ekler ve Kafka aynı mesajı iki kez yazmaz.

Safe Producer

Ise daha geniş bir kavramdır. Hem duplicate’ları önler, hem veri kaybını önler, hem de mesaj sırasını korur. Safe Producer şu ayarların kombinasyonudur:

// Idempotent Producer (duplicate önleme)
enable.idempotence=true

// Veri kaybını önleme
acks=all

// Retry mekanizması
retries=Integer.MAX_VALUE (veya çok yüksek bir değer)
delivery.timeout.ms=120000

// Topic seviyesinde
min.insync.replicas=2
replication.factor=3

Yani şöyle düşünebilirsiniz:

  • Idempotent Producer = Duplicate mesajları önler (tek bir özellik)
  • Safe Producer = Idempotent Producer + Veri kaybını önleme + Mesaj sırası koruma (bir konfigürasyon seti)

Analoji ile Açıklayalım

  • Idempotent Producer: Arabanızın “çarpışma önleme sistemi” gibi. Sadece bir problemi çözer.
  • Safe Producer: Arabanızın tüm güvenlik paketi gibi. Airbag + ABS + Çarpışma önleme + Şerit takip sistemi hepsi bir arada.

Sunumunuzda bahsettiğiniz “Safe Producer” aslında tüm bu güvenlik önlemlerinin bir araya gelmesiyle oluşan konfigürasyondur. Idempotent Producer bunun sadece bir bileşenidir.

Yazıda bu ayrımı daha net yapmalıyım. Teşekkürler bu önemli noktayı sorduğunuz için!

Hepsini Bir Araya Getirelim

Şimdi tüm bu kavramların nasıl birlikte çalıştığını görelim:

Senaryo 1: Başarılı Mesaj Gönderimi

  1. Producer mesajı gönderir (enable.idempotence=true, acks=all)
  2. Leader broker mesajı alır ve PID + sequence number kontrol eder
  3. Mesaj 2 ISR replica’ya yazılır (min.insync.replicas=2)
  4. Tüm ISR’lar ack gönderir
  5. Producer başarılı sonuç alır
  6. Mesaj güvenle saklanmıştır, duplicate yok!

Senaryo 2: Network Hatası ve Retry

  1. Producer mesajı gönderir
  2. Mesaj 2 replica’ya yazılır
  3. Ack gönderilir ama network hatası yüzünden Producer’a ulaşmaz
  4. Producer timeout olur ve mesajı tekrar gönderir (retry)
  5. Broker aynı sequence number’ı görür ve “bu mesajı daha önce aldım” der
  6. Mesajı tekrar yazmaz ama ack gönderir
  7. Producer mutlu, veri duplicate olmamış!

Senaryo 3: Broker Kaybı

  1. 3 broker var (replication.factor=3)
  2. Producer mesaj gönderiyor (acks=all, min.insync.replicas=2)
  3. 1 broker çöker
  4. Geriye 2 broker kalır (min.insync şartı hala sağlanıyor)
  5. Yazma işlemleri devam eder
  6. Eğer bir broker daha çökerse, yazma işlemleri NotEnoughReplicasException hatası verir

Pratik Öneriler

Şimdi size production ortamı için önerilerimi paylaşayım:

1. Kafka 3.0+ Kullanın

Mümkünse Kafka 3.0 veya üzeri kullanın. Bu versiyonlarda güvenli ayarlar varsayılan olarak geliyor. Eski versiyonlarda manuel olarak her şeyi yapmanız gerekir.

2. Kritik Topic’ler İçin

replication.factor=3
min.insync.replicas=2
acks=all
enable.idempotence=true

3. Daha Az Kritik Topic’ler İçin

Eğer biraz veri kaybı tolere edilebilirse:

replication.factor=2
min.insync.replicas=1
acks=1

4. Monitoring Yapın

  • ISR sayısını izleyin
  • Producer error rate’lerini takip edin
  • Broker’ların health durumunu kontrol edin

5. Test Edin!

Production’a geçmeden önce chaos engineering yapın. Broker’ları kapatıp ne olduğunu görün. Network kesintilerini simüle edin. Sisteminizin nasıl davrandığını öğrenin.

Sonuç

Kafka Producer güvenilirliği karmaşık görünebilir ama aslında mantıklı bir sistem. Acks parametresi ne kadar onay istediğinizi, replication factor ve min.insync.replicas dayanıklılık seviyenizi, retry mekanizması geçici hatalara karşı direncini, idempotent producer ise duplicate mesajları önleme yeteneğinizi belirler.

Modern Kafka versiyonları (3.0+) bu ayarları varsayılan olarak güvenli yaptı. Bu harika bir gelişme! Artık yeni başlayanların da “güvenli by default” bir sistem kullanması mümkün.

Unutmayın: Güvenlik ve performans arasında her zaman bir denge vardır. Uygulamanızın ihtiyaçlarına göre bu dengeyi kurun. Finansal bir sistem mi yapıyorsunuz? Maksimum güvenlik! Log aggregation mu? Belki biraz performans öncelikli olabilir.

Umarım bu yazı Kafka Producer güvenilirliği konusunda kafanızdaki soruları yanıtlamıştır. Sorularınız varsa yorum bölümünde buluşalım!

Kaynaklar

[1] Apache Kafka Documentation – Producer Configurations: https://kafka.apache.org/documentation/#producerconfigs

[2] Confluent Documentation – Replication: https://docs.confluent.io/platform/current/kafka/replication.html

[3] Apache Kafka Documentation – min.insync.replicas: https://kafka.apache.org/documentation/#topicconfigs_min.insync.replicas

[4] Confluent Blog – Hands-free Kafka Replication: https://www.confluent.io/blog/hands-free-kafka-replication-a-lesson-in-operational-simplicity/

[5] Apache Kafka Documentation – Producer Retry: https://kafka.apache.org/documentation/#producerconfigs_retries

[6] Apache Kafka Documentation – retry.backoff.ms: https://kafka.apache.org/documentation/#producerconfigs_retry.backoff.ms

[7] Apache Kafka Documentation – delivery.timeout.ms: https://kafka.apache.org/documentation/#producerconfigs_delivery.timeout.ms

[8] Apache Kafka Documentation – max.in.flight.requests.per.connection: https://kafka.apache.org/documentation/#producerconfigs_max.in.flight.requests.per.connection

[9] Confluent Blog – Exactly-once Semantics: https://www.confluent.io/blog/exactly-once-semantics-are-possible-heres-how-apache-kafka-does-it/

[10] Apache Kafka 3.0 Release Notes: https://archive.apache.org/dist/kafka/3.0.0/RELEASE_NOTES.html

0

Bir yanıt yazın

Password Requirements:

  • At least 8 characters
  • At least 1 lowercase letter
  • At least 1 uppercase letter
  • At least 1 numerical number
  • At least 1 special character