Merhaba, bu yazımda sizlere Apache Kafka ‘da bulunan Günlük Sıkıştırma (Log Compaction) özelliğinin ne olduğunu, nasıl çalıştığını ve kullanım alanlarını kısaca anlatmaya çalışacağım.

Apache Kafka, dağınık mimariyle çalışan yüksek performanslı veri akış platformudur.  Temel amacı gerçek zamanlı verilerin yüksek hacim ve düşük geçikme ile üreticiden tüketiciye anahtar-değer (key-value message) ikilisiyle veri taşınmasını sağlamaktır.

Kafka mimarisinde bir veya birden fazla üretici (Producer) konular (Topic) aracılığı ile tüketicilere (Consumer) mesajlarını iletmektedir. Topic içerisinde veriler bölümlere (Partition) ayrılarak Kafka Brokerları üzerinde dağınık bir yapıda tutulur.

Producerlar tarafından üretilen mesajlar verilen key değerine göre  farklı Partitionlar üzerinde tutularak tüketicilere iletilebilir. Her bir mesaj  Partitionlar üzerinde sıralı ve değişmez bir offset değeri ile saklanır.  Consumer verileri tüketirken Partition üzerinde sıradaki offset değerindeki mesajı alarak ilerler.

 

Standart ayarlarda Kafka üzerinde mesajlar  (cleanup.policy=delete) Topic’e tanımlanmış mesaj ömrü kadar (retention-time) veya günlük dosyası büyüklük  (Log-size)  sınırına kadar tutulduktan sonra  eski mesajlar silinir.

nlük sıkıştırma (Log Compaction) nedir?

Günlük sıkıştırma işlemi Kafka’da bir key’e ait verinin her zaman son değerinin Partition üzerinde bulunacağını garanti eder. Partition üzerinde bulunan bir key’e ait yeni bir mesaj geldiğinde Compaction işlemi sonunda   ilgili key’in  eski offsetlerde bulunan verilerini silinerek sadece son değerinin Partition üzerinde kalmasını sağlar.

Log Compaction işleminin öncesini ve sonrasını anlayabilmek için aşağıda bulunan Apache Kafka sitesindenalınmış görseli incelediğimizde; Compaction işleminden önce K1 key’ine ait farklı offsetlerde 4 farklı versiyonda veri bulunur iken compaction işlemi sonrasında K1 key’ine ait sadece 1 değer bulunuyor.

Örneğin müşterilerimizin email değişimlerini tuttuğumuz EMAIL_CHANGES  isimli bir Topic olsun, bir müşteri sistemde email adresini değiştirdiğinde; kullanıcıId değerini key  olarak ve güncel email adresini de değer olarak Kafka’ya  gönderildiğinde Compaction işlemi sonunda kullanıcıId’e ait sadece güncel email adresi Partition kalıyor:

821=> eyyub@company1.com (Offset-1)
.
.
821=> eyyub@company2.com (Offset-5022)
.
.
.
821 => eyyub@company3.com (Offset-9652)

Yukarıda bulunan mesaj sıralaması ile mesajlar geldiğinde Log Compaction işlemi sonrasında Topic kayıtlarında 821 nolu kullanıcıId değerine ait sadece  (Offset-9652) değerindeki eyyub@company3.com email adresi saklanıyor, eski offsetlerde olan mesajlar siliniyor.

1. Günlük sıkıştırma nerelerde kullanılabilirIn-Memory cache kullanan microservislerde: Sistemdeki kullanıcıların son email adresini Kafka’dan  alarak in-memory cache yapısında saklayan ve kullanıcıId ile istek geldiğinde güncel email adresini response olarak döndüren bir microservisimiz olsun. Bu microservis normal çalışma yapısında Kafka üzerinden aktif olarak değişiklikleri alıp kullanıcıId değeri ile cache’ini güncelleyerek çalışıyor olarak kabul edelim.

Bu microservis normal işleyişinde herhangi bir sorun yaşamaz iken restart işlemi sonrasında in-memory cache’i boş olacağı için tüm veriyi Kafka’dan tekrar almak zorunda; bu durumda Log Compaction aktif ise microservis her bir kullanıcı için sadece güncel kaydı alarak cache’ini güncelleyecektir. Eğer Log Compaction yerine time/size retention özelliğini kullansaydık; hem retention periyodu içerisinde kalmayan kayıtlar silinmiş olabilirdi cache hatalı olurdu hem de microservis bir kullanıcıya ait tüm değişimleri teker teker işleyerek geçikme ile çalışmak zorunda kalırdı.

2. Veri değişimlerini izlemenin önemli olmadığı çözümlerde: Telco sektöründen bir senaryoyu ele alalım. Müşterilerin almış oldukları tarife paketlerinde, sözleşmelerde veya adres güncellemelerinde gerçek zamanlı olarak  verileri tek bir json’da toplayarak gsmNo değerini key olarak kullanarak MUSTERI_TOPLU_VERI Kafka Topic’ine gönderiyor olalım.  Farklı departmanlarda hizmet veren uygulamalar bu MUSTERI_TOPLU_VERI Topic’ini dinleyerek; veritabanına zorlu SQL sorguları atma ihtiyacı olmadan güncel bilgileri tek bir merkezden çekebiliyor olsun.  Telco firmalarını düşündüğümüzde saniyede binlerce kayıt üzerinde güncelleme olduğu için time/size retention özelliğini kullanırsak aynı müşteriye ait farklı veriler MUSTERI_TOPLU_VERI Topic’i üzerinde tutulacağı için çok büyük bir saklama alanı gereksinimi ve uzun veri işleme sürelerini gerektirecektir. Günlük Sıkıştırma özelliği ile bir müşteriye ait sadece güncel veri tutulacağı için saklama alanı gereksinimi  optimum noktaya indirilmiş oluyor.

Dikkat edilmesi gereken noktalar neler?

Günlük sıkıştırma özelliği kullandığımızda bazı noktalara dikkat ederek mimari tasarım yapmamız gerekmektedir:

  1. Kafka’ya gönderdiğimiz verilerde Key alanını NULL olarak göndermemeniz gerekiyor.
  2. Bir Topic için Log Compaction özelliğini açtığımızda key bazlı compaction işlemi çalışacağı için I/O ve CPU gereksinimi artacaktır
  3. Gerçek zamanlı (real-time) uygulamalar Topic’i düzenli dinlediği için Compaction periyodu içersinde aynı key’e farklı versiyonlarda veriyi işleyebilir.

Zaman ayırıp okuduğunuz için teşekkürler, görüşmek dileğiyle.