Apache Flink, durumlu hesaplamaları garanti edilmiş doğrulukla işleme yeteneği sayesinde gerçek zamanlı veri işlemenin altın standardı haline gelmiştir. Orta ve ileri düzey geliştiriciler için, Flink'in durumu nasıl yönettiğini ve tam olarak bir kez (exactly-once) semantiğini nasıl sağladığını anlamak isteğe bağlı değildir—veri kaybı veya kopyalama olmadan arızalara dayanabilen güvenilir veri boru hatları oluşturmak için bu bilgi şarttır.
Tam Olarak Bir Kez (Exactly-Once) Semantiğini Anlama
Tam olarak bir kez işleme, sistemin işlem sırasında arızalanması durumunda bile her girdi kaydının nihai çıktıyı tam olarak bir kez etkilemesini sağlayan güçlü bir garantidir. Flink bunu, Kafka'nınkine benzer dağıtık bir işlem sistemi aracılığıyla değil, kontrol noktalarının (checkpoint) ve iki aşamalı taahhüt protokollerinin sofistike bir kombinasyonu ile sağlar.
Temel içgörü, Flink'in yinelenen işlemleri önlemeye çalışmamasıdır. Bunun yerine, herhangi bir yan etkinin (veritabanına yazma gibi) yalnızca tüm kontrol noktası başarıyla tamamlandığında görünür kılınmasını sağlar. Bir arıza meydana gelirse, sistem son başarılı kontrol noktasından geri yüklenir ve kaynaklardan mesajları yeniden oynatır. Kaynak, yeniden oynatmayı desteklemelidir (Kafka ofsetleri gibi), bu nedenle aynı mesajlar tekrar işlenir. Ancak durum kontrol noktasından geri yüklendiği için, mantık, başarısız denemeden kaynaklanan kısmi yan etkileri fiilen "geri alır" veya yok sayar.
Uygulamada Kontrol Noktası Stratejileri
Kontrol noktaları, akış grafiğindeki tüm görevlerin durumunun tutarlı anlık görüntüleridir. Flink bunu başarmak için Chandy-Lamport dağıtık anlık görüntü algoritmasını kullanır. Bir Flink işinde kontrol noktası yapılandırması nasıl yapılır:
Configuration config = new Configuration();
// Kontrol noktası aralığını 1 dakika olarak ayarlayın
config.setString(ExecutionOptionsCheckpoints.CheckpointingMode.KEY, "EXACTLY_ONCE");
env.enableCheckpointing(60000);
// Kontrol noktası durumu arka planını yapılandırın
env.getCheckpointConfig().setCheckpointStorage("hdfs:///flink/checkpoints");
// Kontrol noktası zaman aşımını ve aralığını ayarlayın
env.getCheckpointConfig().setCheckpointTimeout(120000);
env.getCheckpointConfig().setMinPauseBetweenCheckpoints(30000);
Durum arka planının seçimi kritiktir. Küçük durumlar için HashMapStateBackend verimlidir. Daha büyük durumlar için, durumu diske aktararak bellek taşması sorunlarını önlediği için RocksDBStateBackend önerilir:
env.setStateBackend(new RocksDBStateBackend("hdfs:///flink/checkpoints", true));
env.getCheckpointConfig().setCheckpointStorage("hdfs:///flink/checkpoints");
İki Aşamalı Taahhüt ile Yan Etkileri Yönetme
Yerel olarak işlemleri (transaction) desteklemeyen dış sistemlere yazarken, Flink İki Aşamalı Taahhüt Sink API'sini sağlar. Bu, verilerin kontrol noktası başarıyla tamamlanana kadar tüketiciler tarafından görünmez olmasını garanti eder.
// İki Aşamalı Taahhüt Sink kullanan örnek
DataStream<String> output = input
.keyBy("id")
.process(new KeyedProcessFunction<String, String, String>() {
@Override
public void processElement(String value, Context ctx, Collector<String> out) throws Exception {
// Durumu güncelle
ValueState<Integer> counter = getRuntimeContext().getState(
new ValueStateDescriptor<>("counter", Integer.class)
);
int current = counter.value() == null ? 0 : counter.value();
counter.update(current + 1);
out.collect(value + ":" + current);
}
});
// Tam olarak bir kez garantileriyle dış bir sisteme aktar
output.sinkTo(new TwoPhaseCommittingSinkBuilder()
.build());
Üretim Sistemleri İçin En İyi Uygulamalar
- Durum TTL: Sınırsız büyümeyi önlemek için durumunuz için her zaman bir Yaşam Süresi (TTL) tanımlayın. Bayat durumu otomatik olarak temizlemek için
StateTtlConfigkullanın. - Savepoint'ler ve Kontrol Noktaları: Kontrol noktaları otomatik hata toleransı içindir. Savepoint'ler planlı yükseltmeler veya geçişler içindir. Rutin hata kurtarması için savepoint kullanmayın.
- Kontrol Noktası Süresini İzleyin: Kontrol noktaları, kontrol noktası aralığından daha uzun sürüyorsa, sisteminiz baskı altındadır. Aralığı artırın veya durum erişim kalıplarını optimize edin.
Sonuç
Apache Flink'in durumlu işleme yeteneklerini ustalaşmak, kontrol noktalarının ve tam olarak bir kez semantiğinin nasıl etkileşime girdiğini derinlemesine anlamayı gerektirir. Doğru durum arka planını yapılandırarak, yan etkileri iki aşamalı taahhüt protokolleriyle yöneterek ve durum yönetimi için en iyi uygulamalara uyarak, modern veri mimarilerinin taleplerini karşılayacak şekilde ölçeklenebilen, sağlam ve güvenilir akış işleme boru hatları oluşturabilirsiniz.