MongoDB'den Postgres'e
🚨 Bu blog gönderisi, benim MongoDB to Postgres (2024-03-06) ve Sequelize vs. Prisma (2023-05-25) birleştirmemdir. Orijinal bloglar kaldırıldı ve bu blog, ikisi de temelde aynı içeriği/bilgiyi içerdiği için yerlerini aldı. Göç mart 2023’ün başında başladı, geçiş kasım 2023’ün ortasında gerçekleşti ve eski MongoDB sisteminin tüm örnekleri ocak 2024’ün başında tamamen kapatıldı.
Giriş
eBay’de çalıştığım süre boyunca, kariyerimin en teknik açıdan zorlayıcı sorunu haline gelen bir problemle karşılaştım: Depolama Yönetim Sistemi (STMS)‘yi MongoDB’den Postgres’e taşıma. Bu sadece basit bir veritabanı değişimi değildi; eBay’in veri merkezleri boyunca dakikada 1,5 milyondan fazla metriği işleyen kritik bir sistemin tamamen mimari dönüşümüdür ve sıfır kesinti gereksinimiyle neredeyse tüm mevcut işlevselliği korumayı hedefliyordu.
STMS Nedir?
Depolama Yönetim Sistemi (STMS), eBay’in Servis & Depolama Altyapısı (SSI) ekibi için kritik bir iç araç olarak hizmet verir. eBay’in veri merkezleri genelinde cihazları izler ve yönetir, mühendislerin şunları yapmasını sağlar:
- Onlarca dizi, anahtar, ana bilgisayar, disk grubu ve kümeden metrikleri izleyin
- Anahtarlar ve diziler için uyarı yönetimini ele alın
- Ana bilgisayar tahsisleri gibi gelişmiş görevleri tamamlayın
- Diğer iç eBay hizmetleri için gerçek zamanlı verilere erişin
STMS, eBay’in 3 veri merkezinde 70’ten fazla dizi, 60 anahtar, 1100 ana bilgisayar, 900 disk grubu ve 200 küme içerir. Altyapıdaki hayati rolü göz önüne alındığında, herhangi bir kesinti veya işlev kaybı şirketin temel hizmetlerini ve iş operasyonlarını doğrudan etkiler.
Zorluk
Neden Göç Gerekliydi
MongoDB’den Postgres’e geçme kararı hafife alınmadı. MongoDB başlangıçta STMS’ye iyi hizmet vermiş olsa da, veri ilişkilerimizin artan karmaşıklığı ve daha gelişmiş sorgulama yeteneklerine ihtiyaç, Postgres’i kullanım durumumuz için daha uzun vadeli bir çözüm haline getirdi.
Bu Sorunu Zorlaştıran Nelerdi
Bu göçün karmaşıklığı birkaç temel zorluktan kaynaklandı:
1. Temel Veritabanı Farklılıkları
MongoDB ve Postgres temelde farklı veritabanlarıdır. MongoDB, belgeler bazlı bir veritabanıdır (NoSQL), yani veriler koleksiyonlarda JSON olarak saklanır, bir dosya dolabındaki belgeler gibi. Postgres ise ilişkisel bir veritabanıdır (SQL), yani veriler tablolar içinde satır olarak saklanır, bir elektronik tablo gibi.
2. Kod Tabanı Mimarisi
STMS’nin tüm arka ucu, verileri JSON olarak işlemek ve yönetmek için, veritabanı işlemleri için yalnızca MongoDB ile uyumlu paketler kullanılarak inşa edilmişti. Bu, sadece veritabanını değiştirmek değil, tüm uygulamamızın veriyi nasıl işlediğini yeniden yapılandırmak anlamına geliyordu.
3. Sıfır Kesinti Gereksinimi
STMS’nin iç araç olarak ne kadar hayati olduğundan, göç sırasında hiçbir kesinti olamazdı. Sistem, tüm süreç boyunca dakikada 1,5 milyondan fazla metriği hizmet vermeye devam etmeliydi.
4. Sıkı Zaman Çizelgesi ve Sınırlı Deneyim
Göç, birkaç ay içinde tamamlanmalıydı ve başlangıçta net bir yürütme planı yoktu. Ne ben ne de çalışma arkadaşlarım, büyük bir eski kod tabanını NoSQL’den SQL veritabanlarına taşıma deneyimine sahip değildik ve Postgres ile sınırlı bir geçmişim vardı.
5. Ölçek ve Karmaşıklık
Göç, 36 MongoDB koleksiyonunun 74 Postgres tablosuna dönüştürülmesini içeriyordu ve ilişkiler, indeksleme ve sorgu optimizasyonu konusunda dikkatli bir değerlendirme gerektiriyordu.
Doğru ORM’yi Seçmek: Sequelize vs Prisma
İlk büyük kararlardan biri bir ORM (Nesne-İlişkisel Haritalama) aracını seçmekti. Kod tabanımız zaten MongoDB için Mongoose kullanacak şekilde tasarlandığından, bir ORM kullanmak en sorunsuz geçiş yolunu sağlayacaktı.
Gereksinim Analizi
Projenin ihtiyaçlarını dikkatli bir şekilde analiz ettikten sonra, herhangi bir ORM çözümü için temel kriterler belirledim:
- JavaScript paketi olmalı (kodlarımızın çoğu JavaScript ile yazılmıştı)
- Postgres’i ve çoğu özelliğini desteklemeli
- Performans, Mongoose ile eşit ya da daha iyi olmalı
- Açık kaynaklı ve sürdürülen olmalı
Adaylar
Kapsamlı araştırmadan sonra iki ana adayla sınırladım: Sequelize ve Prisma. Postgres için Docker kullanarak kapsamlı test ortamları oluşturdum ve en büyük, en karmaşık veri setimizi belge yapısından tablo yapısına dönüştürdüm.
Test Metodolojisi
Her bir ORM için kritik işlemler üzerindeki performansı ölçtüm:
- Bir giriş oluşturma süresi
- Bir girişi güncelleme süresi
- İç içe girişleri güncelleme süresi (ilişkiler ve JSON anahtar-değerleri)
- Bir girişi silme süresi
- Bir girişi sorgulama/alma süresi
Karar: Sequelize
15 Mayıs 2023 civarında, Sequelize’in kullanım durumumuz için daha iyi bir ORM olduğuna karar verdim. İşte nedenleri:
Sequelize Avantajları:
- Gerçekten açık kaynaklı ve fonlu bir startup tarafından sürdürülmüyor
- Postgres’in çoğu özelliğini destekliyor
- Daha iyi performans, özellikle Prisma’ya kıyasla
- 10 yılı aşkın geliştirme geçmişine sahip olgun bir ekosistem
- JavaScript sınıfları kullanarak esnek model/şema temsili
- Regex dahil karmaşık birleştirmeler ve filtreleme seçenekleri desteği
Performans Sonuçları:
Testlerimde, Sequelize Prisma’ye göre belirgin şekilde daha iyi performans gösterdi. Büyük veri seti girişlerimiz için:
- Sequelize: giriş başına ~2.26 saniye
- Prisma: giriş başına ~11.21 saniye
Prisma, kullanım durumumuz için yaklaşık 5 kat daha yavaştı. Ayrıca, en büyük veri setimizde bir girişi silmek Prisma için neredeyse 4 dakika sürdü, bu gereksinimlerimiz için kabul edilemezdi.
Sequelize Zorlukları:
- Daha karmaşık ve şişirilmiş model temsilleri (Mongoose için 262 satır iken Sequelize 564 satır)
- Belirli durumlarda kafa karıştırıcı sözdizimi
- Veritabanı göçü karmaşıklığı
- Prisma’ya kıyasla daha az kapsamlı dokümantasyon
Sequelize & Prisma Karşılaştırması: Artılar ve Eksiler
Neden Sequelize’i tercih ettiğime dair daha kapsamlı bir resim sunmak için, değerlendirmem sırasında her iki ORM için derlediğim ayrıntılı artı ve eksileri paylaşmak istiyorum. Ayrıca, 15 Mayıs 2023 itibarıyla şema temsili ve topluluk desteği açısından nasıl konumlandıklarına baktım. Bu derinlemesine inceleme seçimimi pekiştirdi ve benzer bir kararla karşılaşan başkalarına faydalı olacağını umuyorum.
Sequelize Artıları:
- sync() fonksiyonuna sahiptir; bu fonksiyon sizin için tabloları otomatik olarak oluşturur ve yönetir, çok fazla manuel çabayı tasarruf eder.
- İç içe veri için karmaşık birleştirmeleri yönetebilir, bu STMS yapısı için kritikti.
- Regex dahil geniş bir filtreleme seçeneği yelpazesi destekler, sorgularda esneklik sağlar.
- Model/şema temsili, sınıflar kullanılarak saf JavaScript’te yapılır; bu, belirli ihtiyaçlara yüksek derecede özelleştirilebilir.
- Veritabanı bağlantılarını sorunsuz yönetir, birden fazla okuma bağlantısı desteği dahil.
- Altta yatan işlemlere inmeniz gerektiğinde saf SQL sorgularını destekler.
- Topluluk istatistikleri 15 Mayıs 2023 itibarıyla: NPM’de, son güncelleme 14 gün önce, haftalık 1.505.835 indirme; GitHub’da, son güncelleme dün, 4.2k Fork ve 27.9k Yıldız. MIT lisansı altında 10 yılı aşkın süredir açık kaynak olduğu için bu şekilde kalacağından eminim.
Sequelize Eksileri:
- Model/şema temsili çok karmaşık ve şişkin hale gelebilir. Örneğin, büyük veri setimizin Mongoose temsili yaklaşık 262 satır (boşluklar dahil) iken, aynı veri seti Sequelize’de 564 satıra yükseldi.
- Sözdizimi belirli senaryolarda kafa karıştırıcı ve karmaşık olabilir, bu da zaman zaman beni yavaşlattı.
- Veritabanını göç ettirmek veya düzenlemek zahmetlidir. sequelize-cli ile göç betikleri oluşturulsa bile hâlâ hantal, ancak bunun çoğu ORM’de ortak bir sorun olduğunu fark ettim.
- Dokümantasyon çok iyi değil, ancak iyileşiyor. Neyse ki, ChatGPT gibi araçlar uzun geçmişi sayesinde Sequelize’i iyi bilir ve eksikleri doldurmaya yardımcı oldu.
- Prisma kadar tip duyarlı değil, bu bazı projelerde sorunlara yol açabilir.
- Sınırlı TypeScript desteği; bu STMS için bir sorun değildi, ancak başkaları için karar verici olabilir.
Prisma Artıları:
- Kendi şema dilini kullanır, model oluşturmayı daha temiz ve öz yapar. Karşılaştırma olarak, Mongoose büyük veri setimiz için 262 satır alırken, Prisma sadece 221 satırda halletti.
- Veritabanı oluşturma ve göçü basitleştiren bir CLI aracına sahiptir; şimdiye kadar gördüğüm en iyi ORM araçlarından biridir, mükemmel olmasa da.
- Gerekli olduğunda esneklik sağlayan saf SQL sorgularını destekler.
- Kod sözdizimi temiz ve Sequelize’ye kıyasla daha anlaşılır, öğrenmesi daha kolay.
- İstemcisi aracılığıyla Node.js ve TypeScript için otomatik sorgu oluşturucular üretir, bu hoş bir özellik.
- Mükemmel, temiz dokümantasyona sahiptir. ChatGPT Prisma konusunda güncel olmasa da resmi dokümanlar bunu telafi eder.
- Topluluk istatistikleri 15 Mayıs 2023 itibarıyla: NPM’de, son güncelleme 6 gün önce, haftalık 1.344.705 indirme; GitHub’da, son güncelleme 3 saat önce, 1.1k Fork ve 31.3k Yıldız.
Prisma Eksileri:
- Postgres için Regex filtrelemeyi desteklemez, ancak “contains”, “includes” ve “startsWith” gibi alternatifler sunar.
- Performans testlerimde büyük bir sorun oldu. Büyük veri setimizde giriş oluşturma Prisma için giriş başına yaklaşık 11.21 saniye, Sequelize ise 2.26 saniye sürdü; yaklaşık 5 kat daha yavaştı.
- Büyük veri setinde tek bir girişi silmek neredeyse 4 dakika sürdü, bu ihtiyaçlarımız için karar verici bir nokta oldu.
- Karmaşık, üç katmanlı ilişki veri setinde adil bir karşılaştırma yapıldığında bile, Sequelize silme işlemlerinde belirgin şekilde daha hızlıydı.
- Prisma, 56,5 milyon dolar fon almış bir startup tarafından destekleniyor. Ana ORM kodu Apache-2.0 altında açık kaynak olsa da, MongoDB’de olduğu gibi gelecekte lisans değişiklikleri olabileceğinden endişeliyim.
Bu ayrıntılı karşılaştırmalar, özellikle performans ve uzun vadeli güvenilirlik açısından, Sequelize’in STMS’nin ihtiyaçlarıyla daha iyi örtüştüğünü ortaya koydu. Ancak bu şekilde bölmek, projelerinde aynı kararla mücadele eden başkalarına yardımcı olabilir diye düşündüm.
Göç Süreci
Veri Yapısı Dönüşümü
MongoDB’nin belge yapısından Postgres’in ilişkisel yapısına dönüştürme, dikkatli bir planlama gerektirdi. Şunları yapmam gerekiyordu:
- İlişkileri Analiz Et: MongoDB belgelerinin birbirleriyle nasıl ilişkili olduğunu belirleyin ve uygun yabancı anahtar ilişkileri tasarlayın
- Verileri Normalleştir: Gerekli durumlarda iç içe belgeleri ayrı tablolara bölün
- JSON Özelliklerini Koru: Gerçekten yapılandırılmamış ve esnek kalması gereken veriler için JSONB sütunları kullanın
- İndeksler Tasarla: Sorgu performansı için uygun indeksler oluşturun
Özel Çözümler
Geçiş, birkaç özel çözüm geliştirmeyi gerektirdi:
1. Veri Göçü Betikleri
Veri göçü betikleri oluşturdum:
- MongoDB koleksiyonlarından verileri çıkarın
- Belge yapılarını ilişkisel formata dönüştürün
- Verileri uygun ilişkilerle Postgres tablolarına aktarın
2. API Uyumluluk Katmanı
Sıfır kesinti sağlamak için, şu işlevleri yerine getirebilen bir uyumluluk katmanı oluşturdum:
- Geçiş durumuna bağlı olarak istekleri MongoDB’ye ya da Postgres’e yönlendirin
- Geçiş sürecinde veri tutarlılığını sağlayın
- Geri dönüş mekanizmaları sağlayın
3. Özel Ara Katman
MongoDB ve Postgres’in belirli işlemleri nasıl ele aldığındaki farkları yönetmek için bir ara katman geliştirdim, mevcut API uç noktalarının değişiklik yapılmadan çalışmaya devam etmesini sağladım.
Teknik Zorlukların Üstesinden Gelme
Karmaşık İlişkileri Yönetme
En büyük zorluklardan biri, MongoDB’nin gömülü belgelerini Postgres ilişkilerine dönüştürmekti. Örneğin, tek bir MongoDB belgesi şunları içerebilir:
- Temel özellikler
- İlgili varlıkları temsil eden iç içe nesneler
- Gömülü belgelerden oluşan diziler
Bunlar dikkatlice şu şekilde ayrılmalıydı:
- Ana varlıklar için birincil tablolar
- Çoktan çoğa ilişkiler için bağlantı tabloları
- Birden çoğa ilişkiler için yabancı anahtar ilişkileri
Sorgu Optimizasyonu
MongoDB’nin sorgu kalıpları doğrudan SQL’e çevrilemez. Şunları yapmam gerekiyordu:
- Karmaşık toplama boru hatlarını SQL birleştirmeleri olarak yeniden yazın
- Yeni sorgu kalıpları için indeksleri optimize edin
- Sorgu performansının MongoDB performansına eşit veya daha iyi olmasını sağlayın
Veri Bütünlüğü
Geçiş sırasında veri bütünlüğünü sağlamak şunları gerektirdi:
- Kapsamlı doğrulama betikleri
- Geri alma prosedürleri
- Geçiş dönemlerinde gerçek zamanlı veri senkronizasyonu
Sonuçlar ve Etki
STMS’nin MongoDB’den Postgres’e geçişi, neredeyse tüm özellik ve işlevselliği koruyarak sıfır kesinti ile başarıyla tamamlandı. Sonuçlar beklentileri aştı:
Performans İyileştirmeleri:
- Karmaşık ilişkisel sorgular için sorgu performansı iyileştirildi
- Daha iyi veri tutarlılığı ve bütünlüğü
- Daha verimli depolama kullanımı
Operasyonel Faydalar:
- Geliştirilmiş izleme ve hata ayıklama yetenekleri
- eBay’in mevcut SQL tabanlı araçlarıyla daha iyi entegrasyon
- Geliştirilmiş yedekleme ve kurtarma prosedürleri
Takım Etkisi:
- Takımın ilişkisel veritabanları konusundaki bilgisinin artırılması
- Gelecek veritabanı geçişleri için kurulan kalıplar
- Yeniden kullanılabilir araçlar ve süreçler oluşturuldu
Kazanılan Teknik Beceriler
Bu proje teknik uzmanlığımı önemli ölçüde genişletti:
Veritabanı Teknolojileri:
- Postgres özellikleri ve optimizasyonu konusunda derin anlayış
- SQL sorgu optimizasyonu ve performans ayarı
- Veritabanı tasarım kalıpları ve normalizasyon
- Birincil-yedek veritabanı yapılandırmaları
Geliştirme Araçları:
- Sequelize ORM ve sorgu oluşturma
- Veritabanı geçiş stratejileri
- Performans test metodolojileri
- Veri doğrulama ve bütünlük kontrolü
Mimari Kalıplar:
- Sıfır kesinti geçiş stratejileri
- API uyumluluk katmanları
- Veritabanı soyutlama kalıpları
- İzleme ve uyarı sistemleri
Kişisel ve Profesyonel Büyüme
Bu geçiş projesi kariyer gelişimim için dönüştürücü oldu. Şunu zorladı
Liderlik Becerileri:
- Önceden deneyim olmadan karmaşık bir teknik projeyi yönetmek
- Baskı altında kritik mimari kararlar almak
- Birden fazla ekip ve paydaşa koordinasyon sağlamak
Problem Çözme Yetkinlikleri:
- Karmaşık problemleri yönetilebilir bileşenlere ayırmak
- Eşi benzeri görülmemiş zorluklara yaratıcı çözümler geliştirmek
- Birden fazla rekabet eden gereksinim ve kısıtlamayı dengelemek
İletişim ve Takım Çalışması:
- Teknik kavramları teknik olmayan paydaşlara açıklamak
- Gelecek referans için süreçleri ve kararları belgelemek
- Yeni teknolojiler ve kalıplar konusunda ekip üyelerine mentorluk yapmak
Öğrenilen Dersler
Teknik Dersler
- Veritabanı Seçimi Önemlidir: NoSQL ve SQL arasındaki seçim, belirli kullanım durumları ve uzun vadeli gereksinimlere dayanmalıdır
- Performans Testi Kritik: Teorik avantajlar her zaman gerçek dünyada performans artışına dönüşmez
- Geçiş Planlaması: Kapsamlı planlama ve test, karmaşık geçişler için esastır
- Araç Yatırımı: Doğru araçları baştan inşa etmek, önemli zaman tasarrufu sağlar ve hataları azaltır
Proje Yönetimi Dersleri
- Paydaş İletişimi: Düzenli güncellemeler ve net iletişim yanlış anlamaları önler
- Risk Yönetimi: Geri dönüş planları ve geri alma prosedürlerine sahip olmak esastır
- Zaman Çizelgesi Yönetimi: Beklenmeyen zorluklar ve öğrenme eğrileri için tampon zaman ayırın
- Dokümantasyon: Kapsamlı dokümantasyon bilgi transferini ve gelecekteki bakımı mümkün kılar
Sonuç
STMS MongoDB’den Postgres’e geçiş, kariyerimde çözdüğüm en zor ve ödüllendirici teknik problem olarak durmaktadır. Sadece teknik uzmanlık değil, aynı zamanda liderlik, planlama ve uyum yeteneği de gerektirdi. Projenin başarısı, doğru planlama, kapsamlı test ve mükemmeliyete bağlılıkla, en karmaşık teknik zorlukların bile üstesinden gelinebileceğini gösterdi.
Bu deneyim, yazılım mühendisliğine yaklaşımımı temelden değiştirdi ve şu önemin altını çizdi:
- Teknik kararlar almadan önce tam bağlamı ve gereksinimleri anlamak
- Doğru araçlar ve testlere zaman ayırmak
- Karmaşık projeler boyunca net iletişimi sürdürmek
- Gerekli olduğunda yeni teknolojileri ve yaklaşımları öğrenmeye istekli olmak
Geçişin başarısı, sadece STMS’nin yeteneklerini artırmakla kalmadı, aynı zamanda eBay’in altyapı projelerine fayda sağlayan kalıplar ve süreçler oluşturdu. Bilinmeyen zorlukları benimsemenin ve onlardan başarıyla çıkmanın, hem kişisel hem de profesyonel gelişim için anahtar olduğuna inancımı pekiştirdi.
Geriye baktığımda, bu proje kariyerimde bir dönüm noktasıdır; beni çözümler uygulayan bir geliştiriciden, karmaşık teknik girişimleri tasarlayıp yönlendirebilen bir mühendise dönüştürdü. Bu deneyimden elde edilen güven ve beceriler, yazılım mühendisliğinde yeni zorluklar ve fırsatlara yaklaşımımı yönlendirmeye devam ediyor.