İçeriğe atla

Case study / Monafy / 1 / 2. bölüm

Kafka tüketicisi yeniden başladığında nereden devam etmeli?

Kısa cevapVeri kaydı ile offset ayrı ilerlerse yeniden başlatmada boşluk oluşabilir. İkisini aynı PostgreSQL transaction’ında tutmak bu sınırı açık hale getirir.

Monafy’de fiyatları tek bir servis yayımlıyor, diğer servisler bu olayları Kafka üzerinden okuyor. Tüketici bir mesajı işlerken yalnız fiyatı güncellemiyor; ürünün sonraki parçalarının kullandığı sıra bilgisini de ilerletiyor. Bu nedenle veriyi yazmak ile mesajı tüketilmiş saymak arasındaki sınır kritik.

Kullandığımız istemci kütüphanesinin hata davranışını incelerken, işleyici başarısız olsa da tüketim konumunun ilerleyebildiğini gördük. Konumu yalnız Kafka’ya bırakmak yerine PostgreSQL’de uygulama verisiyle birlikte tutmaya karar verdik.

Veri kaydı ile tüketim konumu arasındaki boşluk

Veri yazıldıktan sonra konum kaydedilmeden süreç durursa mesaj yeniden gelir. Konum ilerlemiş, veri kaydı tamamlanmamışsa bu kez mesaj uygulama açısından eksik kalabilir. Sıra numarasıyla çalışan alt sistemler için bu ayrımın açık olması gerekiyordu.

İstemci kütüphanesini tamamen değiştirmedik. Tüketim döngüsünü kullanmaya devam ederken, hatanın nasıl dışarı taşındığını ve konumun ne zaman kaydedildiğini kendi kontrolümüze aldık. İşleyicinin başarısızlığı normal tamamlanma gibi kabul edilmiyor.

Konum ve veriyi birlikte commit etmek

Bir mesaj grubu uygulanırken tüketici konumu da aynı veritabanı transaction’ında yazılıyor. İşlem tamamlanırsa ikisi birlikte kalıcı oluyor; geri alınırsa ikisi de önceki durumda kalıyor. Yeniden başlayan tüketici, başlangıç noktasını uygulamanın kayıtlı konumundan alıyor.

Kafka’daki konum bilgisi izleme araçları için yine güncelleniyor, ancak veritabanı commit’inden sonra. İşleme doğruluğunun kaynağı bu ikinci kayıt değil, veriyle birlikte yazılmış konum. Bu tercih bütün dış sistemler için kendiliğinden bir kez işleme garantisi vermiyor; sınır PostgreSQL transaction’ı içinde.

Kararı anlatan sadeleştirilmiş örnekte veri ile ilerleme bilgisi aynı işlem sınırında tutuluyor:

PHP
1DB::transaction(function () use ($batch, $position) {
2    applyBatch($batch);
3    savePosition($position);
4});

Tek bir sorunlu kayıt grubun tamamını bekletebilir

Bu atomiklik bilinçli bir bedel taşıyor. Veritabanının reddettiği tek kayıt, aynı gruptaki diğer kayıtların da geri alınmasına neden oluyor. Tüketici, hata giderilene kadar aynı konumdan ilerlemeyi deniyor. Kayıt atlayarak devam etmek yerine nedenin görünür kılınması gerekiyor.

Dolayısıyla konumu güvenli tutmak tek başına yeterli değil. Sürecin çalışıyor görünmesi ile gerçekten ilerlemesi farklı durumlar. Kayıtlı konumun değişimini ve akışın gerisinde kalmayı ayrıca izlemek gerekiyor.

Doğrulamada yeniden başlatma senaryosu

Bu tasarımın anlamlı kontrolü, yalnız başarılı mesajı yazmak değil, işleme sırasında duran tüketicinin nereden devam ettiğini görmek. Yeniden işleme, eksik kayıt ve konum ilerlemesi aynı senaryoda incelenmeli. Akışın süre tarafını ise Kafka fiyat akışındaki gecikme yazısında ayrı ele alıyorum.

Monafy hakkında yazılar

Monafy ile Türkiye ve ABD borsalarında şirket araştırması Canlı fiyatlar neden gecikir? Kafka hattında gecikme analizi CLAUDE.md ile bağlam yönetimi ve paralel AI oturumları

Birlikte çalışalım

Benzer bir proje mi düşünüyorsun?

Projeni anlat