MongoDB'den Postgres'e
🚨 Bu blog gönderisi, benim MongoDB’den Postgres’e (2024-03-06) ve Sequelize vs. Prisma (2023-05-25) birleştirmesidir. Orijinal bloglar kaldırıldı ve bu blog, ikisi de temelde aynı içeriği/bilgiyi içerdiği için yerini almıştır. 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’deki görevim sırasında, kariyerimdeki en teknik açıdan zorlayıcı problemle karşılaştım: Depolama Yönetim Sistemi (STMS)’ni MongoDB’den Postgres’e taşımak. Bu sadece basit bir veritabanı değişimi değildi; eBay 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 süresi ile mevcut işlevselliğin neredeyse tamamını koruma gereksinimi vardı.
STMS Nedir?
Depolama Yönetim Sistemi (STMS), eBay’in Servis & Depolama Altyapısı (SSI) ekibi için kritik bir iç araçtır. Sistem, eBay veri merkezlerindeki cihazları izler ve yönetir, mühendislerin şunları yapmasını sağlar:
- Onlarca dizi, anahtar, sunucu, disk grubu ve kümeden metrikleri izlemek
- Anahtarlar ve diziler için uyarı yönetimi
- Sunucu tahsisleri gibi gelişmiş görevleri tamamlamak
- Diğer iç eBay hizmetleri için gerçek zamanlı verilere erişim sağlamak
STMS, 3 eBay veri merkezinde 70’ten fazla dizi, 60 anahtar, 1100 sunucu, 900 disk grubu ve 200 küme içerir. Altyapıdaki kritik rolü nedeniyle, herhangi bir kesinti veya işlev kaybı şirketin temel hizmetlerini ve iş operasyonlarını doğrudan etkiler.
Zorluk
Göçün Neden Gerekli Olduğu
MongoDB’den Postgres’e geçme kararı hafife alınmadı. MongoDB başlangıçta STMS’yi iyi hizmet etse de, veri ilişkilerimizin artan karmaşıklığı ve daha gelişmiş sorgulama yeteneklerine duyulan ihtiyaç, Postgres’i uzun vadeli çözüm olarak daha uygun kıldı.
Bu Sorunu Zorlaştıran Unsurlar
Göçün karmaşıklığı birkaç temel zorluktan kaynaklandı:
1. Temel Veritabanı Farklılıkları
MongoDB ve Postgres temelde farklı veritabanlarıdır. MongoDB, belge tabanlı bir veritabanıdır (NoSQL) ve veriler koleksiyonlardaki JSON olarak saklanır; bir dosya dolabındaki belgeler gibi. Postgres ise ilişkisel bir veritabanıdır (SQL) ve veriler tabloların satırları 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 üzere, yalnızca MongoDB ile uyumlu paketler kullanılarak inşa edilmişti. Bu, sadece veritabanını değiştirmek değil, tüm uygulamanın veri işleme şeklini 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+ milyon metriği sunmaya 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 legacy kod tabanını NoSQL’den SQL veritabanına taşımada deneyime sahip değildik ve Postgres konusunda sınırlı önceden deneyimim vardı.
5. Ölçek ve Karmaşıklık
Göç, 36 MongoDB koleksiyonunu 74 Postgres tablosuna dönüştürmeyi içeriyordu; ilişkiler, indeksleme ve sorgu optimizasyonu dikkatle ele alınmalıydı.
Doğru ORM’nin Seçimi: Sequelize vs Prisma
İlk büyük karar, bir ORM (Object-Relational Mapping) aracı seçmekti. Kod tabanımız zaten MongoDB için Mongoose kullanacak şekilde tasarlandığından, bir ORM kullanmak geçiş yolunu en sorunsuz hâle getirecekti.
Gereksinim Analizi
Projenin ihtiyaçlarını dikkatlice analiz ettikten sonra, herhangi bir ORM çözümü için temel kriterleri belirledim:
- JavaScript paketi olmalı (kodumuzun çoğu JavaScript ile yazılmıştı)
- Postgres’i ve çoğu özelliğini desteklemeli
- Performans en az Mongoose ile eşdeğer ya da daha iyi olmalı
- Açık kaynak ve sürdürülebilir olmalı
Adaylar
Yoğun araştırma sonrası iki ana aday ortaya çıktı: Sequelize ve Prisma. Docker kullanarak Postgres için 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 ORM için kritik operasyonlarda performans ölçtüm:
- Bir kayıt oluşturma süresi
- Bir kaydı güncelleme süresi
- İç içe kayıtları (ilişkiler ve JSON anahtar-değerleri) güncelleme süresi
- Bir kaydı silme süresi
- Bir kaydı sorgulama/çekme süresi
Karar: Sequelize
15 Mayıs 2023 civarında, projemiz için Sequelize’ın daha iyi bir ORM olduğuna karar verdim. İşte nedenleri:
Sequelize Avantajları:
- Gerçekten açık kaynak ve finanse edilen bir startup tarafından sürdürülmüyor
- Postgres’in çoğu özelliğini destekliyor
- Özellikle Prisma’ya kıyasla daha iyi performans
- 10 yılı aşkın süredir geliştirilen olgun bir ekosistem
- JavaScript sınıflarıyla esnek model/şema temsili
- Regex dahil karmaşık join ve filtreleme seçenekleri desteği
Performans Sonuçları:
Testlerimde Sequelize, Prisma’dan belirgin şekilde daha hızlıydı. Büyük veri seti kayıtları için:
- Sequelize: kayıt başına ~2.26 saniye
- Prisma: kayıt başına ~11.21 saniye
Prisma, kullanım senaryomuzda yaklaşık 5 kat daha yavaştı. Ayrıca, en büyük veri setimizde bir kaydı silmek Prisma ile neredeyse 4 dakika sürdü; bu gereksinimlerimiz için kabul edilemezdi.
Sequelize Zorlukları:
- Daha karmaşık ve şişkin model temsilleri (564 satır vs Mongoose için 262 satır)
- Bazı 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
Sequelize’ı seçmemin nedenlerini daha net göstermek için, değerlendirme sürecinde her iki ORM için derlediğim ayrıntılı artı ve eksileri paylaşmak istiyorum. Ayrıca, Mayıs 15, 2023 itibarıyla şema temsili ve topluluk desteği açısından nasıl konumlandıklarını inceledim. Bu derinlemesine analiz, seçimimi pekiştirdi ve benzer bir kararla karşılaşacak diğerlerine faydalı olabilir.
Sequelize Artıları:
- sync() fonksiyonu, tabloları otomatik olarak oluşturur ve yönetir, bu da çok fazla manuel çaba tasarrufu sağlar.
- STMS yapısı için kritik olan iç içe veri için karmaşık join’leri yönetebilir.
- Regex dahil geniş bir filtreleme yelpazesi sunar, sorgularda esneklik sağlar.
- Model/şema temsili, sınıflarla ham JavaScript’te yapılır; belirli ihtiyaçlara yüksek derecede özelleştirilebilir.
- Çoklu okuma bağlantılarını destekleyerek veritabanı bağlantılarını sorunsuz yönetir.
- Gerektiğinde alt seviyeye inmek için ham SQL sorgularını destekler.
- Mayıs 15, 2023 itibarıyla topluluk istatistikleri: NPM’de son 14 günde 1.505.835 haftalık indirme; GitHub’da dün güncellenmiş, 4.2k Fork ve 27.9k Star. 10 yılı aşkın süredir MIT lisansı altında açık kaynak, bu yüzden gelecekte de aynı kalacağından eminim.
Sequelize Eksileri:
- Model/şema temsili çok karmaşık ve şişkin hale gelebilir. Örneğin, büyük veri setimiz Mongoose ile 262 satır iken, aynı veri seti Sequelize’da 564 satıra çıktı.
- Sözdizimi bazı senaryolarda kafa karıştırıcı ve karmaşık, bu da zaman zaman yavaşlamama neden oldu.
- Veritabanı göçü veya düzenlemesi zahmetli. sequelize-cli ile migration scriptleri oluşturulsa da hâlâ hantal; bu, çoğu ORM’de ortak bir sıkıntı.
- Dokümantasyon çok iyi değil, ancak gelişiyor. Neyse ki, ChatGPT gibi araçlar uzun geçmişi sayesinde Sequelize hakkında sağlam bir bilgiye sahip ve eksikleri doldurabiliyor.
- Prisma kadar tip duyarlı değil, bu bazı projelerde sorun yaratabilir.
- TypeScript desteği sınırlı; bu STMS için sorun olmadı, ancak başkaları için karar verici olabilir.
Prisma Artıları:
- Kendi şema dilini kullanır, model oluşturmayı daha temiz ve öz hâle getirir. Örneğin, büyük veri setimiz Mongoose ile 262 satır iken, Prisma sadece 221 satırda halletti.
- Veritabanı oluşturma ve göçü basitleştiren bir CLI aracı sunar; şu ana kadar gördüğüm en iyi ORM araçlarından biri, mükemmel olmasa da.
- Gerektiğinde ham SQL sorgularını destekler, esneklik sağlar.
- Kod sözdizimi temiz ve Sequelize’a göre daha basit, öğrenmesi daha kolay.
- Node.js ve TypeScript için sorgu oluşturucuları otomatik olarak client üzerinden üretir, bu hoş bir dokunuş.
- Mükemmel, temiz dokümantasyona sahip. ChatGPT Prisma konusunda güncel olmayabilir, ancak resmi dokümantasyon bunu telafi eder.
- Mayıs 15, 2023 itibarıyla topluluk istatistikleri: NPM’de son 6 günde 1.344.705 haftalık indirme; GitHub’da 3 saat önce güncellenmiş, 1.1k Fork ve 31.3k Star.
Prisma Eksileri:
- Postgres için Regex filtrelemesini desteklemez; bunun yerine “contains”, “includes” ve “startsWith” gibi alternatifler sunar.
- Performans testlerimde büyük bir sorun oldu. Büyük veri setimizde bir kayıt oluşturma süresi Prisma için yaklaşık 11.21 saniye, Sequelize için 2.26 saniye; yani yaklaşık 5 kat daha yavaş.
- Büyük veri setinde tek bir kaydı silmek neredeyse 4 dakika sürdü; bu bizim ihtiyaçlarımız için kabul edilemezdi.
- Üç katmanlı derin ilişki veri setinde adil bir karşılaştırma yapıldığında bile, silme işlemlerinde Sequelize belirgin şekilde daha hızlıydı.
- Prisma, 56.5 milyon dolar finansman almış bir startup tarafından destekleniyor. ORM kodu Apache-2.0 altında açık kaynak olsa da, MongoDB’de olduğu gibi lisans değişiklikleri riskine karşı temkinliyim.
Bu ayrıntılı karşılaştırmalar, Sequelize’ın STMS’nin ihtiyaçlarıyla, özellikle performans ve uzun vadeli güvenilirlik açısından daha uyumlu olduğunu gösterdi. Ancak bu şekilde bölüştürmek, benzer bir seçimle karşılaşan diğerlerine yardımcı olabilir.
Göç Süreci
Veri Yapısı Dönüşümü
MongoDB’nin belge yapısından Postgres’in ilişkisel yapısına geçiş, dikkatli bir planlama gerektirdi. Şunları yapmam gerekiyordu:
- İlişkileri Analiz Et: MongoDB belgelerinin birbirleriyle nasıl ilişkili olduğunu belirle ve uygun yabancı anahtar ilişkileri tasarla
- Verileri Normalleştir: Gömülü belgeleri gerektiğinde ayrı tablolara böl
- JSON Özelliklerini Koru: Gerçekten yapılandırılmamış ve esnek kalması gereken veriler için JSONB sütunları kullan
- İndeksleri Tasarla: Sorgu performansı için uygun indeksler oluştur
Özel Çözümler
Geçiş, birkaç özel çözüm geliştirmeyi gerektirdi:
1. Veri Geçiş Betikleri
Kapsamlı betikler oluşturdum:
- MongoDB koleksiyonlarından verileri çıkar
- Belge yapılarını ilişkisel formata dönüştür
- Verileri uygun ilişkilerle Postgres tablolarına içe aktar
2. API Uyumluluk Katmanı
Sıfır kesinti sağlamak için, şu işlevi görebilen bir uyumluluk katmanı inşa ettim:
- Geçiş durumuna bağlı olarak istekleri MongoDB ya da Postgres’e yönlendir
- Geçiş sürecinde veri tutarlılığını sağla
- Geri dönüş mekanizmaları sun
3. Özel Ara Katman
MongoDB ve Postgres’in belirli işlemleri nasıl ele aldığındaki farkları yönetmek için ara katman geliştirdim; böylece mevcut API uç noktaları değişiklik yapmadan çalışmaya devam etti.
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 birleşim 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ı yapmak zorunda kaldım:
- Karmaşık toplama boru hatlarını SQL birleştirmeleri olarak yeniden yaz
- Yeni sorgu kalıpları için indeksleri optimize et
- Sorgu performansının MongoDB performansını karşılamasını ya da aşmasını sağla
Veri Bütünlüğü
Geçiş sırasında veri bütünlüğünü sağlamak için şunlar gerekliydi:
- Kapsamlı doğrulama betikleri
- Geri alma prosedürleri
- Geçiş dönemlerinde gerçek zamanlı veri senkronizasyonu
Sonuçlar ve Etki
MongoDB’den Postgres’e STMS geçişi, neredeyse tüm özellik ve işlevselliği koruyarak sıfır kesintiyle başarıyla tamamlandı. Sonuçlar beklentileri aştı:
Performans İyileştirmeleri:
- Karmaşık ilişkisel sorgular için sorgu performansı iyileşti
- 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 bilgi birikiminin artması
- Gelecek veritabanı geçişleri için kalıpların oluşturulması
- Yeniden kullanılabilir araç ve süreçlerin yaratılması
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ı konfigürasyonları
Geliştirme Araçları:
- Sequelize ORM ve sorgu oluşturma
- Veritabanı geçiş stratejileri
- Performans testi 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. Beni keşfedilmemiş bir alana itti ve şunları gerektirdi:
Liderlik Becerileri:
- Önceden deneyim olmadan karmaşık bir teknik projeyi yönetmek
- Baskı altında kritik mimari kararlar almak
- Birden çok takım ve paydaşa koordinasyon sağlamak
Problem Çözme Yetileri:
- Karmaşık problemleri yönetilebilir bileşenlere ayırmak
- Eşi benzeri görülmemiş zorluklara yaratıcı çözümler geliştirmek
- Birden çok rekabet eden gereksinim ve kısıtlamayı dengelemek
İletişim ve Takım Çalışması:
- Teknik kavramları teknik olmayan paydaşlara açıklamak
- Gelecek referanslar için süreç ve kararları belgelemek
- Takım üyelerine yeni teknolojiler ve kalıplar konusunda mentorluk yapmak
Öğrenilen Dersler
Teknik Dersler
- Veritabanı Seçimi Önemlidir: NoSQL ve SQL arasındaki seçim, belirli kullanım durumları ve uzun vadeli gereksinimler temelinde yapılmalıdır
- Performans Testi Kritik: Teorik avantajlar her zaman gerçek dünya performans kazançlarına dönüşmez
- Geçiş Planlaması: Kapsamlı planlama ve test, karmaşık geçişler için vazgeçilmezdir
- 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: Beklenmedik zorluklar ve öğrenme eğrileri için tampon zaman ayır
- Dokümantasyon: Ayrıntılı dokümantasyon, bilgi transferini ve gelecekteki bakımı mümkün kılar
Sonuç
STMS MongoDB’den Postgres’e geçişi, kariyerimde çözdüğüm en zor ve en ö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 önemi vurguladı:
- 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’in yeteneklerini artırmakla kalmadı, aynı zamanda eBay’in altyapı projelerine fayda sağlayan kalıpları ve süreçleri de kurdu. Bilinmeyen zorlukları kucaklamanın ve bunların üstesinden gelmenin, hem kişisel hem de profesyonel gelişim için anahtar olduğuna olan 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öneten bir mühendise dönüştürdü. Bu deneyimden elde edilen güven ve beceriler, yeni zorluklar ve fırsatlar karşısında yazılım mühendisliğine yaklaşımımı yönlendirmeye devam ediyor.