MongoDB'den Postgres'e
NOT: Bu blog yazısı, benim MongoDB’den Postgres’e (2024-03-06) ve Sequelize vs. Prisma (2023-05-25) yazılarımın bir birleşimidir. Orijinal bloglar kaldırıldı ve bu blog onların yerini aldı; çünkü ikisi de esasen aynı içerik/bilgiyi barındırıyordu. Taşıma işlemi Mart 2023’ün başlarında başladı, geçiş Kasım 2023’ün ortalarında gerçekleşti ve eski MongoDB sisteminin tüm örnekleri Ocak 2024’ün başlarında tamamen kapatıldı.
Giriş
eBay’de çalıştığım süre boyunca, kariyerimin teknik açıdan en zor problemi haline gelen bir durumla karşılaştım: Depolama Yönetim Sistemi’ni (STMS) MongoDB’den Postgres’e taşımak. Bu, yalnızca basit bir veritabanı değişimi değildi; eBay’in veri merkezleri genelinde dakikada 1,5 milyondan fazla metriği alan, sıfır kesinti gereksinimiyle ve mevcut işlevselliğin neredeyse tamamını koruyarak kritik bir sistemin tamamen mimari dönüşümüydü.
STMS nedir?
Depolama Yönetim Sistemi (STMS), eBay’in Hizmet ve Depolama Altyapısı (SSI) ekibi için kritik bir dahili araç olarak hizmet verir. eBay’in veri merkezleri genelindeki cihazları izler ve yönetir; mühendislerin şunları yapmasına olanak tanır:
- Düzinece dizi, anahtar, ana bilgisayar, disk grubu ve kümelerden gelen metrikleri izlemek
- Anahtarlar ve diziler için uyarı yönetimi yapmak
- Ana bilgisayar tahsisleri gibi gelişmiş görevleri tamamlamak
- Diğer dahili eBay hizmetleri için gerçek zamanlı verilere erişmek
STMS, eBay’in 3 veri merkezindeki 70’ten fazla dizi, 60 anahtar, 1100 ana bilgisayar, 900 disk grubu ve 200 kümeden sorumludur. eBay’in altyapısındaki hayati rolü göz önüne alındığında, herhangi bir kesinti ya da işlev kaybı şirketin temel hizmetlerini ve iş operasyonlarını doğrudan etkilerdi.
Zorluk
Taşımanın Neden Gerekli Olduğu
MongoDB’den Postgres’e geçme kararı hafife alınarak verilmedi. MongoDB başlangıçta STMS’ye iyi hizmet etmiş olsa da, veri ilişkilerimizin giderek artan karmaşıklığı ve daha gelişmiş sorgulama yeteneklerine duyulan ihtiyaç, kullanım senaryomuz için Postgres’i daha iyi bir uzun vadeli çözüm haline getirdi.
Bu Problemi Zorlaştıran Şey
Bu taşımanın karmaşıklığı birkaç temel zorluktan kaynaklanıyordu:
1. Temel Veritabanı Farklılıkları MongoDB ve Postgres temelde farklı veritabanlarıdır. MongoDB belge tabanlı bir veritabanıdır (NoSQL); yani veriler, bir dosya dolabındaki belgeler gibi koleksiyonlar içinde JSON olarak saklanır. Postgres ilişkisel bir veritabanıdır (SQL); yani veriler, bir elektronik tabloda olduğu gibi tablolar içinde satırlar halinde saklanır.
2. Kod Tabanı Mimarisi STMS’nin tüm arka ucu, verileri JSON’lar olarak işleyip yönetmek üzere oluşturulmuştu ve veritabanı işlemleri için yalnızca MongoDB ile uyumlu paketler kullanıyordu. Bu da yalnızca veritabanını değiştirmek değil, tüm uygulamamızın veriyi ele alış biçimini yeniden yapılandırmak anlamına geliyordu.
3. Sıfır Kesinti Gereksinimi STMS dahili bir araç olarak ne kadar kritik olduğundan, taşıma sırasında hiçbir kesinti olamazdı. Sistem, tüm süreç boyunca dakikada 1,5 milyondan fazla metriğe hizmet vermeye devam etmek zorundaydı.
4. Dar Zaman Çizelgesi ve Sınırlı Deneyim Taşımanın birkaç ay içinde tamamlanması gerekiyordu ve başlangıçta net bir uygulama planı yoktu. Ne ben ne de iş arkadaşlarım, büyük bir eski kod tabanını NoSQL’den SQL veritabanlarına taşımak konusunda deneyime sahip değildik ve benim de Postgres ile önceki deneyimim sınırlıydı.
5. Ölçek ve Karmaşıklık Taşıma, 36 MongoDB koleksiyonunun 74 Postgres tablosuna dönüştürülmesini içeriyordu; bu da ilişkiler, indeksleme ve sorgu optimizasyonu konusunda dikkatli bir değerlendirme gerektiriyordu.
Doğru ORM’i Seçmek: Sequelize vs Prisma
İlk büyük kararlardan biri bir ORM (Nesne-İlişkisel Eşleme) aracı 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ı dikkatlice analiz ettikten sonra, herhangi bir ORM çözümü için temel ölçütleri belirledim:
- Bir JavaScript paketi olmalıydı (kodumuzun çoğu JavaScript ile yazılmıştı)
- Postgres’i ve özelliklerinin çoğunu desteklemeliydi
- Performansı en az Mongoose kadar iyi, tercihen daha iyi olmalıydı
- Açık kaynak olmalı ve aktif olarak sürdürülmeliydi
Adaylar
Yoğun araştırmalardan sonra, iki ana aday üzerinde karar kıldım: Sequelize ve Prisma. Postgres için Docker kullanarak kapsamlı test ortamları oluşturdum ve en büyük, en karmaşık veri kümemizi belge yapısından tablo yapısına dönüştürdüm.
Test Metodolojisi
Her ORM için kritik işlemler boyunca performansı ölçtüm:
- Bir kayıt oluşturma süresi
- Bir kaydı güncelleme süresi
- İç içe kayıtları güncelleme süresi (ilişkiler ve JSON anahtar-değerleri)
- Bir kaydı silme süresi
- Bir kaydı sorgulama/alma süresi
Karar: Sequelize
2023-05-15 civarında, Sequelize’nin kullanım senaryomuz için daha iyi ORM olduğuna karar verdim. İşte nedenleri:
Sequelize Avantajları:
- Gerçek anlamda açık kaynaklı ve fonlanan bir startup tarafından sürdürülmüyor
- Postgres’in özelliklerinin çoğunu destekliyordu
- Daha iyi performans, özellikle Prisma ile karşılaştırıldığında
- 10 yılı aşkın geliştirme geçmişine sahip olgun ekosistem
- JavaScript sınıfları kullanarak esnek model/şema gösterimi
- Regex dahil karmaşık birleştirmeler ve filtreleme seçenekleri desteği
Performans Sonuçları:
Testlerimde Sequelize, Prisma’dan belirgin şekilde daha iyi performans gösterdi. Büyük veri seti kayıtlarımız için:
- Sequelize: kayıt başına ~2,26 saniye
- Prisma: kayıt başına ~11,21 saniye
Prisma, kullanım senaryomuz için Sequelize’den yaklaşık 5 kat daha yavaştı. Ayrıca, en büyük veri setimizden bir kaydı silmek Prisma’da neredeyse 4 dakika sürdü; bu da gereksinimlerimiz için kabul edilemezdi.
Sequelize Zorlukları:
- Daha karmaşık ve şişkin model gösterimleri (Mongoose için 262 satıra karşı 564 satır)
- Bazı durumlarda kafa karıştırıcı sözdizimi
- Veritabanı taşıma karmaşıklığı
- Prisma’ya kıyasla daha az kapsamlı dokümantasyon
Sequelize ve Prisma’nın Artı ve Eksi Karşılaştırması
Neden Sequelize’i seçtiğime dair daha eksiksiz bir resim sunmak için, değerlendirmem sırasında her iki ORM için derlediğim ayrıntılı artı ve eksi yönleri paylaşmak istiyorum. Ayrıca 15 Mayıs 2023 itibarıyla şema gösterimi ve topluluk desteği açısından nasıl karşılaştırıldıklarına da baktım. Bu daha derin inceleme, seçimimi sağlamlaştırmama yardımcı oldu ve benzer bir kararla karşı karşıya kalan başkaları için de yararlı olabileceğini umuyorum.
Sequelize Artıları:
- Sizin için tabloları otomatik olarak oluşturan ve yöneten bir sync() fonksiyonuna sahiptir; bu da çok fazla manuel emeği kurtarır.
- STMS’nin yapısı için kritik olan iç içe verilerde karmaşık birleştirmeleri yönetebilir.
- Regex dahil çok çeşitli filtreleme seçeneklerini destekler; bu da sorgularda esneklik sağlar.
- Model/şema gösterimi, belirli ihtiyaçlara uyacak şekilde son derece özelleştirilebilir sınıflar kullanılarak ham JavaScript ile yapılır.
- Birden fazla okuma bağlantısı desteği dahil olmak üzere veritabanı bağlantılarını sorunsuz şekilde yönetir.
- Detaylara inmeniz gerektiğinde ham SQL sorgularını destekler.
- 15 Mayıs 2023 itibarıyla topluluk istatistikleri: NPM’de son güncelleme 14 gün önce, haftalık 1.505.835 indirme; GitHub’da son güncelleme dün, 4,2 bin Fork ve 27,9 bin Yıldız. 10 yılı aşkın süredir MIT lisansı ile açık kaynak olduğundan, bunun böyle kalacağından eminim.
Sequelize Eksileri:
- Model/şema gösterimi çok karmaşık ve şişkin hale gelebilir. Örneğin, büyük veri setimizin Mongoose gösterimi yaklaşık 262 satırdı (boşluklar dahil), aynı veri seti Sequelize’de 564 satıra çıktı.
- Sözdizimi bazı senaryolarda kafa karıştırıcı ve karmaşık olabilir; bu da zaman zaman beni yavaşlattı.
- Veritabanını taşımak veya düzenlemek zahmetlidir. sequelize-cli taşıma betikleri üretse bile, yine de kullanışsızdır; ancak bunun çoğu ORM’de yaygın bir ağrı noktası olduğunu fark ettim.
- Dokümantasyon harika değil, ancak gelişiyor. Neyse ki ChatGPT gibi araçlar, uzun geçmişi sayesinde Sequelize konusunda sağlam bir kavrayışa sahip; bu da eksikleri doldurmaya yardımcı oldu.
- Prisma kadar tür-duyarlı değildir; bu da bazı projelerde sorunlara yol açabilir.
- Sınırlı TypeScript desteği vardır; bu STMS için bir sorun olmasa da, başkaları için belirleyici bir engel olabilir.
Prisma Artıları:
- Kendi şema dilini kullanır; bu da model oluşturmayı daha temiz ve daha öz hale getirir. Karşılaştırma için, Mongoose büyük veri setimiz için 262 satır alırken, Prisma bunu yalnızca 221 satırda başardı.
- Veritabanı oluşturma ve taşımayı basitleştiren bir CLI aracıyla gelir; bu, şimdiye kadar bir ORM’den gördüğüm en iyisi, kusursuz olmasa da.
- Gerektiğinde esneklik sunarak ham SQL sorgularını destekler.
- Kod sözdizimi, Sequelize ile karşılaştırıldığında temiz ve anlaşılması daha basittir; bu da öğrenmeyi kolaylaştırır.
- İstemcisi aracılığıyla Node.js ve TypeScript için sorgu oluşturucuları otomatik olarak üretir; bu hoş bir ayrıntıdır.
- Mükemmel ve temiz bir dokümantasyona sahiptir. ChatGPT Prisma konusunda o kadar güncel değildir, ancak resmi dokümanlar çoğu zaman bunu telafi etmiştir.
- 15 Mayıs 2023 itibarıyla topluluk istatistikleri: NPM’de son güncelleme 6 gün önce, haftalık 1.344.705 indirme; GitHub’da son güncelleme 3 saat önce, 1,1 bin Fork ve 31,3 bin Yıldız.
Prisma Eksileri:
- Postgres için Regex filtrelemeyi desteklemez; ancak “contains”, “includes” ve “startsWith” gibi alternatifler sunar.
- Testlerimde performans büyük bir sorundu. Büyük veri setimiz için kayıt oluşturma, Sequelize’nin 2,26 saniyesine kıyasla Prisma’da kayıt başına yaklaşık 11,21 saniye sürdü; bu da yaklaşık 5 kat daha yavaştı.
- Büyük veri setinden tek bir kaydı silmek neredeyse 4 dakika sürdü; bu da ihtiyaçlarımız açısından bir anlaşmayı bozan durumdu.
- Karmaşık, üç katman derinliğinde bir ilişkiler 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 fonlamaya sahip bir startup tarafından destekleniyor. Ana ORM kodu Apache-2.0 altında açık kaynak olsa da, MongoDB’de olanlara benzer şekilde ileride olası lisans değişiklikleri konusunda temkinliyim.
Bu ayrıntılı karşılaştırmalar, özellikle performans ve uzun vadeli güvenilirlik açısından Sequelize’nin STMS’nin ihtiyaçlarıyla daha iyi uyum sağladığını açıkça ortaya koydu. Ama bunu böyle parçalara ayırmanın, projeleri için aynı kararla boğuşan başkalarına yardımcı olabileceğini düşündüm.
Taşıma 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 planlama gerektirdi. Şunları yapmak zorundaydım:
- İlişkileri Analiz Etmek: MongoDB belgelerinin birbirleriyle nasıl ilişkili olduğunu belirlemek ve uygun yabancı anahtar ilişkileri tasarlamak
- Veriyi Normalleştirmek: İç içe geçmiş belgeleri uygun yerlerde ayrı tablolara ayırmak
- JSON Özelliklerini Korumak: Gerçekten yapılandırılmamış ve esnek kalması gereken veriler için JSONB sütunları kullanmak
- Dizinler Tasarlamak: Sorgu performansı için uygun dizinler oluşturmak
Özel Çözümler
Taşıma, birkaç özel çözüm geliştirmeyi gerektirdi:
1. Veri Taşıma Betikleri
Aşağıdakileri yapmak için kapsamlı betikler oluşturdum:
- MongoDB koleksiyonlarından veri çıkarmak
- Belge yapılarını ilişkisel biçime dönüştürmek
- Veriyi doğru ilişkilerle Postgres tablolarına içe aktarmak
2. API Uyumluluk Katmanı
Sıfır kesinti sağlamak için, şunları yapabilen bir uyumluluk katmanı geliştirdim:
- İstekleri taşıma durumuna bağlı olarak MongoDB veya Postgres’e yönlendirmek
- Geçiş döneminde veri tutarlılığını sağlamak
- Yedekleme mekanizmaları sağlamak
3. Özel Ara Katman Yazılımı
MongoDB ve Postgres’in belirli işlemleri ele alış biçimlerindeki farklılıkları yönetmek için ara katman yazılımı geliştirdim; böylece mevcut API uç noktaları değişiklik yapılmadan çalışmaya devam etti.
Teknik Zorlukların Üstesinden Gelmek
Karmaşık İlişkileri Ele Almak
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
- İlişkili varlıkları temsil eden iç içe nesneler
- Gömülü belgelerden oluşan diziler
Bu yapı, dikkatlice şu biçimde ayrıştırılmak zorundaydı:
- Ana varlıklar için birincil tablolar
- Bire-çok ilişkiler için ara tablolar
- Bire-çok ilişkiler için yabancı anahtar ilişkileri
Sorgu Optimizasyonu
MongoDB’nin sorgu kalıpları doğrudan SQL’e çevrilmez. Şunları yapmak zorundaydım:
- Karmaşık toplama boru hatlarını SQL join’leri olarak yeniden yazmak
- Yeni sorgu kalıpları için dizinleri optimize etmek
- Sorgu performansının MongoDB performansını karşılamasını veya aşmasını sağlamak
Veri Bütünlüğü
Taşıma 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 taşınması, neredeyse tüm özellikler ve işlevler korunurken sıfır kesintiyle başarıyla tamamlandı. Sonuçlar beklentileri aştı:
Performans İyileştirmeleri:
- Karmaşık ilişkisel sorgularda 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
- İyileştirilmiş yedekleme ve kurtarma prosedürleri
Ekip Etkisi:
- Ekipte ilişkisel veritabanları konusundaki bilginin artması
- Gelecekteki veritabanı taşımaları için kalıpların oluşturulması
- Yeniden kullanılabilir araçlar ve süreçler oluşturulması
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 normalleştirme
- Birincil-yedek veritabanı yapılandırmaları
Geliştirme Araçları:
- Sequelize ORM ve sorgu oluşturma
- Veritabanı taşıma stratejileri
- Performans test metodolojileri
- Veri doğrulama ve bütünlük kontrolü
Mimari Kalıplar:
- Sıfır kesintili taşıma stratejileri
- API uyumluluk katmanları
- Veritabanı soyutlama kalıpları
- İzleme ve uyarı sistemleri
Kişisel ve Profesyonel Gelişim
Bu taşıma projesi, kariyer gelişimim için dönüştürücü oldu. Beni bilinmeyen bir alana itti ve şunları gerektirdi:
Liderlik Becerileri:
- Önceden deneyim olmadan karmaşık bir teknik projeyi yönetmek
- Baskı altında kritik mimari kararlar vermek
- Birden fazla ekip ve paydaşla koordinasyon kurmak
Problem Çözme Yetkinlikleri:
- Karmaşık sorunları yönetilebilir bileşenlere ayırmak
- Emsalsiz zorluklar için yaratıcı çözümler geliştirmek
- Birden fazla rekabet eden gereksinim ve kısıtı dengelemek
İletişim ve Ekip Çalışması:
- Teknik kavramları teknik olmayan paydaşlara açıklamak
- Süreçleri ve kararları gelecekte başvurmak üzere belgelemek
- Ekip üyelerine yeni teknolojiler ve kalıplar konusunda mentorluk yapmak
Öğrenilen Dersler
Teknik Dersler
- Veritabanı Seçimi Önemlidir: NoSQL ve SQL arasındaki seçim, özel kullanım senaryolarına ve uzun vadeli gereksinimlere dayanmalıdır
- Performans Testi Kritik Öneme Sahiptir: Teorik avantajlar her zaman gerçek dünyadaki performans kazanımlarına dönüşmez
- Taşıma Planlaması: Kapsamlı planlama ve test, karmaşık taşımalar için zorunludur
- Araçlara Yatırım: Başta doğru araçları geliştirmek önemli ölçüde zaman kazandırır ve hataları azaltır
Proje Yönetimi Dersleri
- Paydaş İletişimi: Düzenli güncellemeler ve net iletişim yanlış anlaşılmaları önler
- Risk Yönetimi: Yedek planlara ve geri alma prosedürlerine sahip olmak zorunludur
- Zaman Çizelgesi Yönetimi: Beklenmedik zorluklar ve öğrenme eğrileri için zaman payı bırakmak gerekir
- Dokümantasyon: Kapsamlı dokümantasyon, bilgi aktarımını ve gelecekteki bakımı mümkün kılar
Sonuç
STMS’nin MongoDB’den Postgres’e taşınması, kariyerimde çözdüğüm en zorlayıcı ve en ödüllendirici teknik sorun olarak öne çıkıyor. Bu, yalnızca teknik uzmanlık değil, aynı zamanda liderlik, planlama ve uyum sağlama becerisi de gerektirdi. Projenin başarısı, doğru planlama, kapsamlı test ve mükemmelliğe bağlılık ile en karmaşık teknik zorlukların bile aşılabileceğini gösterdi.
Bu deneyim, yazılım mühendisliğine yaklaşımımı temelden değiştirdi ve şunların önemini vurguladı:
- Teknik kararlar vermeden önce bağlamın ve gereksinimlerin tamamını anlamak
- Doğru araçlara ve teste zaman ayırmak
- Karmaşık projeler boyunca net iletişimi sürdürmek
- Gerektiğinde yeni teknolojileri ve yaklaşımları öğrenmeye istekli olmak
Taşımanın başarısı yalnızca STMS’nin yeteneklerini geliştirmekle kalmadı, aynı zamanda eBay’in altyapı projelerine fayda sağlamaya devam eden kalıplar ve süreçler de oluşturdu. Bilinmeyen zorlukları benimsemenin ve onları başarıyla aşmanın, hem kişisel hem de profesyonel gelişimin anahtarı olduğuna dair inancımı pekiştirdi.
Geriye baktığımda, bu proje kariyerimde bir dönüm noktasını temsil ediyor; beni çözümler uygulayan bir geliştiriciden, karmaşık teknik girişimleri mimarlandırıp yönetebilen bir mühendise dönüştürdü. Bu deneyimden kazandığım özgüven ve beceriler, yazılım mühendisliğinde yeni zorluklara ve fırsatlara yaklaşımımı yönlendirmeye devam ediyor.