Monolitik mimarilerden mikro hizmetlere geçiş, aşamalı göç stratejilerine olan kritik bir ihtiyaç yaratmıştır. Kuruluşlar, özellikle Oracle veya SQL Server eski sistemleri ile ölçekli olarak çalışanlar için, dünya durdurma göçlerini yapma lüksüne sahip olamazlar. Bu soru, işletmelerin yıllarca süren tarihsel veri bütünlüğünden vazgeçmeden veya saatler süren bakım pencerelerini kabul etmeden modernleşmesi gereken gerçekteki senaryolardan ortaya çıkmıştır.
Temel zorluk, monolitik ACID işlemleri ile mikro hizmetlerin dağıtık doğası arasındaki uyumsuzluktur. Bir veritabanını parçalayarak, hem eski sistemde hem de yeni hizmetlerde güncellemelerin aynı anda gerçekleştiği bir split-brain senaryosuyla karşılaşırsınız. Her iki sistemi çalışır durumda tutarken ağ sınırları boyunca referans bütünlüğünü sağlamak, basit veritabanı çoğaltması ile çözülemeyen bir dağıtık uzlaşım problemi oluşturur.
Güvenilir olay yayınını sağlamak için Change Data Capture (CDC) ile Event-Driven Architecture uygulamak. Eski veritabanı işlem günlüklerinden satır düzeyindeki değişiklikleri yakalamak için Debezium bağlayıcılarını dağıtın, olayları merkezi sinir sistemi olarak Apache Kafka'ya akıtarak. Aynı anda, mikro hizmetler katmanında dağıtık işlemleri yönetmek için Saga Pattern uygulayın, her hizmetin operasyonel özerkliğini korurken nihai tutarlılığı sağlamaya özen gösterin.
Bir Fortune 500 e-ticaret platformu, on yıllık Oracle monolitini PostgreSQL tabanlı mikro hizmetlere göç ettirmesi gerekti. Stok, fiyatlandırma ve sipariş tamamlama modülleri, on iki ana tablo arasında yabancı anahtar kısıtlarıyla sıkı bir şekilde bağlıydı. Tatil sezonlarında, sistem veri kaybı veya kesinti toleransı olmaksızın dakikada 50.000 işlem gerçekleştiriyordu.
Çözüm A: Çift Yazma Stratejisi
Mühendislik ekibi başlangıçta eski uygulama kodunu hem Oracle hem de yeni PostgreSQL hizmetlerine aynı anda yazacak şekilde değiştirmeyi düşündü. Bu yaklaşım, yazma işlemlerinin senkron ve tutarlı kalmasını sağlayarak basitlik vaadi sundu. Ancak, yeni hizmet gecikme yaşarsa veya başarısız olursa tüm eski sistemin çökme riski yaratıyordu. Ayrıca, XA protokolü aracılığıyla dağıtık işlemleri uygulamak performansı ciddi oranda düşürür, zirve yük altında yanıt sürelerini %400 artırırdı.
Çözüm B: Veritabanı Tetikleyicileri ve Görünümler
Başka bir seçenek, Oracle'da veri satırı değişiklikleri için REST uç noktalarını doğrudan tetikleyen veritabanı tetikleyicileri oluşturmaktı. Bu, uygulama değişiklikleri gerektirmediği için çekici görünüyordu. Ancak, bu durumda veritabanı altyapısı ile ağ topolojisi arasında sıkı bir bağlılık yarattı, sistemi kırılgan hale getirdi. Mikro hizmet uç noktası erişilemez hale gelirse, tetikleyici başarısız olur ve bu da tüm eski işlemin geri alınmasına yol açar—bu da sıfır kesinti gereksinimini ihlal eder. Ayrıca, tetikleyicilerin belirli sütun yapılarına bağlı olması nedeniyle şema göçlerini yönetmek neredeyse imkansız hale geliyordu.
Çözüm C: Olay Kaydı ile Değişiklik Verisi Yakalama
Seçilen mimari, Debezium kullanarak Oracle'ın yeniden günlüğüne bakarak her ekleme, güncelleme ve silmeyi değiştirilmez olaylar olarak yakaladı ve bunları Apache Kafka'ya yayınladı. Mikro hizmetler bu olayları Kafka Streams aracılığıyla tüketerek PostgreSQL'ye dönüştürdü ve sakladı, böylece tam olarak bir kez anlamını güvence altına alan Outbox Pattern uygulandı. Confluent tarafından yönetilen bir Schema Registry, Avro şemaları kullanarak geriye ve ileriye dönük uyumluluğu sağladı. Bu, eski sistemi göç karmaşasından kopardı—Oracle yeni mimari hakkında habersiz kaldı, hizmetler olayları kendi hızlarında tükettikleri sırada.
Seçilen çözüm ve mantığı
Ekip, Çözüm C'yi seçti çünkü Tek Sorumluluk Prensibine saygı gösterdi ve hata izolasyonu sağladı. Çift yazımla karşılaştırıldığında, eski sistemin performansı mikro hizmet gecikmesinden etkilenmedi. Tetikleyicilere kıyasla, Debezium kilitlemeden çalıştı. Olay günlüğü değişmez bir denetim izi sağladı ve Kafka'nın saklama politikaları, mikro hizmetlerin şema evrimi sırasında yeniden işleme ihtiyaç duyduklarında tarihsel verilerin tekrar oynatılmasını sağladı.
Sonuç
Sekiz aylık bir göçün ardından, platform başarıyla 200TB’lik işlem verisini %99.97 çalışma süresi ile taşıdı. Sistem, önceki yıla göre %40 daha düşük gecikme ile Black Friday trafiğini yönetti. Yeni hizmetlerde bir fiyat hesaplama hatası keşfedildiğinde, ekip üç gün boyunca Kafka'dan olayları yeniden oynattı ve eski Oracle sistemine dokunmadan 2.3 milyon kaydı düzeltti. CDC hattı artık Apache Flink kullanarak gerçek zamanlı analitik için temel işlevi görüyor.
Mikro hizmetler CDC olaylarını tüketirken monolit değiştiğinde şema evrimini nasıl ele alıyorsunuz?
Adaylar sıklıkla göç sırasında şemanın dondurulmasını önermektedir, bu ise çevik iş için pratik değildir. Doğru yaklaşım, Confluent Schema Registry'ni Avro şemaları ile ileri ve geri uyumluluk modlarını kullanarak uygulamaktır. Oracle tabloları değiştiğinde, Debezium bağlayıcısı güncellenmiş şemalarla olayları yayınlar, ancak kayıt defteri uyumluluk kurallarını uygular. Hizmetler, Apache Avro'nun çözüm kurallarını kullanarak şemanın okunması modelini uygulamalıdır—bilinmeyen alanları göz ardı ederek ve eksik olanlar için varsayılan değerler kullanarak. Ayrıca, okuma modellerinin kaynak şemadan bağımsız olarak evrim geçirebileceği bir CQRS deseni uygulayın, Kafka Connect dönüştürücüleri ile iç içe geçmiş yapıları tüketim uç noktalarına ulaşmadan önce düzleştirerek.
Her iki sistem de geçiş döneminde aynı varlığı aynı anda güncellerse ne olur?
Bu, basit zaman damgalarının çözemeyeceği bir split-brain senaryosu yaratır. Mimarlar, belirleyici çatışma çözümü için Vector Clocks veya CRDT'ler (Çatışmasız Yeniden Üretilen Veri Türleri) uygulamalıdır. Mikro hizmet olaylarını tüketen ve yazılan verileri Oracle'a geri yazan bir İki Yönlü Senkronizasyon bileşeni dağıtın, ancak hibrit mantıksal saatlere dayalı katı Son-Yazma-Kazanan (LWW) anlamları ile.
Daha da önemlisi, Domain-Driven Design sınırlarını uygulayın—göç sırasında, bir toplam kök başına yazma mülkiyetini yalnızca monolit veya mikro hizmete atayın, asla her ikisine birden. Göç durumunu belirtmek için Oracle'da Database Flags kullanarak yazma trafiğini yönlendirin ve bunu Strangler Fig Pattern'i kullanarak bir API Gateway üzerinden yönlendirin.
Ticari bir operasyon hem eski veritabanını hem de yeni mikro hizmetleri kapsadığında, işlem bütünlüğünü sağlamak için desen nasıl tanımlarsınız?
Çoğu aday, heterojen sistemlerde İki Aşamalı Taahhüt (2PC) kullanarak dağıtık işlemleri önerir, bu da kırılgan bağlılık ve kullanılabilirlik sorunları yaratır. Doğru çözüm, Saga Pattern ile Tamamlayıcı İşlemler uygulamaktadır. Bir kullanıcı eylemi hem Oracle (eski) hem de PostgreSQL (yeni) üzerinde güncelleme gerektiriyorsa, bunu Camunda veya Temporal üzerinde inşa edilen bir Saga Orkestratör ile organize edin. Süreç, yerel işlemleri sıralı olarak yürütür: önce Oracle’ı güncelle, ardından bir alan olayı yayınla, sonra mikro hizmet operasyonunu gerçekleştir. Herhangi bir adım başarısız olursa, tamamlayıcı işlemleri yürütün—eğer mikro hizmet taahhüdü başarısız olursa, eski sistemin geri alması için dönüp Oracle değişikliğini geri almak üzere bir geri alma olayı tetikleyin. Bu, ağ sınırları boyunca kaynakları kilitlemeden nihai tutarlılığı korur.