Yüksek verimlilikli veri mühendisliği alanında veri bütünlüğünü sağlamak hayati önem taşır. Dağıtık olay akışlarıyla uğraşırken "en az bir kez" ve "tam bir kez" teslimat kavramları yalnızca teorik değildir; güvenilir boru hatları oluşturmak için kritik öneme sahiptir. Ancak, Apache Kafka gibi dağıtık bir sistemde gerçek tam bir kez semantiğine ulaşmak karmaşıktır ve çoğu zaman üretici yapılandırmaları, işlem API'leri ve kopyaları yönetmek ile sıralamayı korumak için dikkatli tüketici mantığının bir kombinasyonunu gerektirir.
Dağıtık Sistemlerde Kopyaların Meydana Getirdiği Zorluk
Dağıtık mimarilerde ağ arızaları kaçınılmazdır. Bir mesaj gönderilebilir ancak onay kaybolabilir, bu da üreticinin yeniden denemesine neden olur. Önlemler alınmazsa bu durum kopyalara yol açar. Bazı sistemler tüketici tarafında kopya temizleme yoluyla bunu tolere edebilirken, diğerleri her kaydın tam olarak bir kez işlendiğine dair sıkı bir garanti gerektirir. Kafka, bunu üretici düzeyinde idempotent üreticiler ve uçtan uca düzeyde işlemler ile ele alır.
İdempotent Üreticilerin Uygulanması
İdempotensi, aynı kaydın tek bir bölüm içinde bir konuya birden fazla kez yazılmadığını garanti eder. Bu, enable.idempotence=true üretici yapılandırmasıyla kontrol edilir. Etkinleştirildiğinde, üretici her bölüm için bir sıra numarası tutar. Broker, bu sıra numaralarını izler ve aynı üreticiden gelen sırasız veya kopya mesajları reddeder.
Properties props = new Properties();
props.put(ProducerConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");
props.put(ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
props.put(ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG, StringSerializer.class.getName());
// İdempotent üreticiyi etkinleştir
props.put(ProducerConfig.ENABLE_IDEMPOTENCE_CONFIG, true);
KafkaProducer<String, String> producer = new KafkaProducer<>(props);
producer.send(new ProducerRecord<String, String>("my-topic", "key", "value"));
İdempotent üreticilerin yalnızca tek bir bölüm içinde kopya temizleme garantisi verdiğini not etmek önemlidir. Bir mesaj yeniden denendiğinde ve farklı bir bölüme yönlendirilirse (anahtar değişiklikleri veya bölümleyici sorunları nedeniyle), idempotensi bölümler arası kopyaları önleyemez.
Uçtan Uca Tam Bir Kez Semantiğine Ölçekleme
Birden fazla konu ve harici sistemler arasında gerçek tam bir kez semantiğine ulaşmak için Kafka, İşlem API'sini sağlar. Bu, üreticilerin birden fazla konuya atomik olarak yazmasına olanak tanır. Tüketiciler, isolation.level=read_committed ayarını kullanarak bu işlemlere katılabilir ve yalnızca taahhüt edilmiş işlem verilerini okumalarını sağlayabilir.
String transactionalId = "unique-transaction-id";
producer.initTransactions();
producer.beginTransaction();
try {
producer.send(new ProducerRecord<String, String>("topic-a", "value1"));
producer.send(new ProducerRecord<String, String>("topic-b", "value2"));
producer.commitTransaction();
} catch (KafkaException e) {
producer.abortTransaction();
}
Tüketicilerde Sıralama ve Kopyaların Yönetimi
Tam bir kez yazımlara sahip olsanız bile, ofsetlerin sıfırlanabileceği veya bir tüketici grubu yeniden dengesizleşmesinin (rebalance) gerçekleşebileceği sınır durumlarını ele almak için tüketici mantığı idempotent olmalıdır. Sağlam bir desen, işlenmiş mesaj kimlikleri için yerel bir durum deposu tutmayı veya kopyaları işlemeden önce reddetmek için benzersiz kısıtlamaları olan bir veritabanı kullanmayı içerir.
Sonuç
Apache Kafka'da tam bir kez semantiğine ulaşmak çok katmanlı bir yaklaşım gerektirir. Temel yeniden denemeleri ele almak için idempotent üreticilerle başlayın, konular arası atomik yazımlar için Kafka işlemlerinden yararlanın ve tüketici mantığınızı doğası gereği idempotent olacak şekilde tasarlayın. Bu stratejileri birleştirerek, geçici arızalar karşısında bile veri bütünlüğünü koruyan sağlam, yüksek verimlilikli olay akışları oluşturabilirsiniz.