MongoDB ke Postgres

CATATAN: Tulisan blog ini merupakan gabungan dari MongoDB ke Postgres (2024-03-06) dan Sequelize vs. Prisma (2023-05-25). Blog asli telah dihapus, dan blog ini telah mengambil tempatnya karena keduanya pada dasarnya berisi konten/informasi yang sama. Migrasi dimulai pada awal Maret 2023, perpindahan terjadi pada pertengahan November 2023, dan semua instansi sistem MongoDB lama sepenuhnya dimatikan pada awal Januari 2024.

Pendahuluan

Selama saya bekerja di eBay, saya menghadapi apa yang menjadi masalah paling menantang secara teknis dalam karier saya: memigrasikan Storage Management System (STMS) dari MongoDB ke Postgres. Ini bukan sekadar penggantian basis data biasa; ini adalah transformasi arsitektur total dari sebuah sistem kritis yang menyerap lebih dari 1,5 juta metrik per menit di seluruh pusat data eBay, dengan persyaratan tanpa waktu henti dan mempertahankan hampir semua fungsi yang sudah ada.

Apa itu STMS?

Storage Management System (STMS) berfungsi sebagai alat internal penting bagi tim Service & Storage Infrastructure (SSI) eBay. Sistem ini memantau dan mengelola perangkat di seluruh pusat data eBay, memungkinkan para insinyur untuk:

  • Memantau metrik dari puluhan array, switch, host, grup disk, dan klaster
  • Menangani pemberian peringatan untuk switch dan array
  • Menyelesaikan tugas lanjutan seperti alokasi host
  • Mengakses data waktu nyata untuk layanan internal eBay lainnya

STMS mencakup lebih dari 70 array, 60 switch, 1100 host, 900 grup disk, dan 200 klaster di 3 pusat data eBay. Mengingat perannya yang vital dalam infrastruktur eBay, setiap waktu henti atau kehilangan fungsi akan berdampak langsung pada layanan inti dan operasi bisnis perusahaan.

Tantangan

Mengapa Migrasi Ini Diperlukan

Keputusan untuk bermigrasi dari MongoDB ke Postgres tidak diambil dengan enteng. Meskipun MongoDB pada awalnya telah melayani STMS dengan baik, meningkatnya kompleksitas relasi data kami dan kebutuhan akan kemampuan kueri yang lebih canggih menjadikan Postgres solusi jangka panjang yang lebih baik untuk kasus penggunaan kami.

Apa yang Membuat Masalah Ini Sulit

Kompleksitas migrasi ini berasal dari beberapa tantangan mendasar:

1. Perbedaan Mendasar Basis Data MongoDB dan Postgres adalah basis data yang secara fundamental berbeda. MongoDB adalah basis data berbasis dokumen (NoSQL), yang berarti data disimpan sebagai JSON dalam koleksi, seperti dokumen di lemari arsip. Postgres adalah basis data relasional (SQL), yang berarti data disimpan sebagai baris dalam tabel, seperti dalam spreadsheet.

2. Arsitektur Basis Kode Seluruh backend STMS dibangun untuk memproses dan mengelola data sebagai JSON, menggunakan paket yang secara eksklusif kompatibel dengan MongoDB untuk operasi basis data. Ini berarti bukan hanya mengganti basis data, tetapi juga merestrukturisasi cara seluruh aplikasi kami menangani data.

3. Persyaratan Tanpa Waktu Henti Karena betapa vitalnya STMS sebagai alat internal, tidak boleh ada waktu henti selama migrasi. Sistem harus terus melayani 1,5+ juta metrik per menit sepanjang proses berlangsung.

4. Jangka Waktu Ketat & Pengalaman Terbatas Migrasi harus diselesaikan dalam beberapa bulan, tanpa rencana pelaksanaan yang jelas pada awalnya. Baik saya maupun rekan kerja saya tidak memiliki pengalaman memigrasikan basis kode lama berskala besar dari basis data NoSQL ke SQL, dan saya memiliki pengalaman sebelumnya yang terbatas dengan Postgres.

5. Skala & Kompleksitas Migrasi ini melibatkan konversi 36 koleksi MongoDB menjadi 74 tabel Postgres, yang memerlukan pertimbangan cermat terhadap relasi, pengindeksan, dan optimisasi kueri.

Memilih ORM yang Tepat: Sequelize vs Prisma

Salah satu keputusan besar pertama adalah memilih alat ORM (Object-Relational Mapping). Karena basis kode kami sudah dirancang untuk menggunakan Mongoose untuk MongoDB, menggunakan ORM akan memberikan jalur transisi yang paling mulus.

Analisis Kebutuhan

Setelah analisis cermat terhadap kebutuhan proyek, saya menetapkan kriteria penting untuk solusi ORM apa pun:

  • Harus berupa paket JavaScript (sebagian besar kode kami ditulis dalam JavaScript)
  • Harus mendukung Postgres dan sebagian besar fiturnya
  • Performa harus setidaknya setara atau lebih baik daripada Mongoose
  • Harus bersifat sumber terbuka dan dipelihara

Kandidatnya

Setelah riset ekstensif, saya mempersempit pilihan menjadi dua penantang utama: Sequelize dan Prisma. Saya membuat lingkungan pengujian komprehensif menggunakan Docker untuk Postgres dan mengonversi dataset terbesar dan paling kompleks kami dari struktur dokumen ke struktur tabel.

Metodologi Pengujian

Untuk setiap ORM, saya mengukur performa pada operasi-operasi kritis:

  • Waktu untuk membuat entri
  • Waktu untuk memperbarui entri
  • Waktu untuk memperbarui entri bertingkat (relasi dan key-value JSON)
  • Waktu untuk menghapus entri
  • Waktu untuk menanyakan/mengambil entri

Keputusan: Sequelize

Sekitar 15 Mei 2023, saya memutuskan bahwa Sequelize adalah ORM yang lebih baik untuk kasus penggunaan kami. Berikut alasannya:

Keunggulan Sequelize:

  • Benar-benar sumber terbuka dan tidak dipelihara oleh startup yang didanai
  • Mendukung sebagian besar fitur Postgres
  • Performa lebih baik, terutama dibandingkan Prisma
  • Ekosistem matang dengan lebih dari 10 tahun pengembangan
  • Representasi model/skema yang fleksibel menggunakan kelas JavaScript
  • Dukungan untuk join kompleks dan opsi penyaringan termasuk Regex

Hasil Performa:

Dalam pengujian saya, Sequelize secara signifikan mengungguli Prisma. Untuk entri dataset besar kami:

  • Sequelize: ~2,26 detik per entri
  • Prisma: ~11,21 detik per entri

Prisma sekitar 5x lebih lambat daripada Sequelize untuk kasus penggunaan kami. Selain itu, menghapus satu entri dari dataset terbesar kami membutuhkan waktu hampir 4 menit di Prisma, yang tidak dapat diterima untuk kebutuhan kami.

Tantangan Sequelize:

  • Representasi model yang lebih kompleks dan membengkak (564 baris vs 262 baris untuk Mongoose)
  • Sintaks yang membingungkan dalam kasus tertentu
  • Kompleksitas migrasi basis data
  • Dokumentasi yang kurang komprehensif dibandingkan Prisma

Perbandingan Kelebihan & Kekurangan Sequelize & Prisma

Untuk memberikan gambaran yang lebih lengkap tentang alasan saya memilih Sequelize, saya ingin membagikan kelebihan dan kekurangan terperinci yang saya kumpulkan untuk kedua ORM selama evaluasi saya. Saya juga melihat bagaimana keduanya dibandingkan dalam hal representasi skema dan dukungan komunitas per 15 Mei 2023. Penjelajahan lebih mendalam ini membantu meneguhkan pilihan saya, dan saya harap ini juga bisa berguna bagi orang lain yang menghadapi keputusan serupa.

Kelebihan Sequelize:

  • Memiliki fungsi sync() yang secara otomatis membuat dan menangani tabel untuk Anda, menghemat banyak upaya manual.
  • Dapat menangani join kompleks untuk data bertingkat, yang sangat penting bagi struktur STMS.
  • Mendukung berbagai opsi penyaringan, termasuk Regex, sehingga memberikan fleksibilitas dalam kueri.
  • Representasi model/skema dilakukan dalam JavaScript mentah menggunakan kelas, yang sangat dapat disesuaikan untuk memenuhi kebutuhan spesifik.
  • Menangani koneksi basis data dengan mulus, termasuk dukungan untuk banyak koneksi baca.
  • Mendukung kueri SQL mentah saat Anda perlu melihat lebih dalam.
  • Statistik komunitas per 15 Mei 2023: Di NPM, terakhir diperbarui 14 hari yang lalu dengan 1.505.835 unduhan mingguan; di GitHub, terakhir diperbarui kemarin dengan 4,2k Fork dan 27,9k Bintang. Ini telah menjadi sumber terbuka dengan lisensi MIT selama lebih dari 10 tahun, jadi saya yakin itu akan tetap seperti itu.

Kekurangan Sequelize:

  • Representasi model/skema bisa menjadi sangat kompleks dan membengkak. Misalnya, sementara representasi Mongoose untuk dataset besar kami sekitar 262 baris (termasuk spasi), dataset yang sama di Sequelize membengkak menjadi 564 baris.
  • Sintaksnya bisa membingungkan dan rumit dalam skenario tertentu, yang kadang memperlambat saya.
  • Memigrasikan atau mengedit basis data merepotkan. Bahkan dengan sequelize-cli yang menghasilkan skrip migrasi, itu tetap merepotkan, meskipun saya menyadari ini adalah masalah umum pada sebagian besar ORM.
  • Dokumentasinya tidak terlalu bagus, meskipun semakin membaik. Untungnya, alat seperti ChatGPT memiliki pemahaman yang kuat tentang Sequelize karena sejarahnya yang panjang, yang membantu menutup celah.
  • Tidak sepeka tipe seperti Prisma, yang dapat menyebabkan masalah pada beberapa proyek.
  • Dukungan TypeScript terbatas, meskipun ini bukan masalah bagi STMS, ini bisa menjadi penghalang bagi orang lain.

Kelebihan Prisma:

  • Menggunakan bahasa skemanya sendiri, sehingga pembuatan model menjadi lebih rapi dan lebih ringkas. Sebagai perbandingan, sementara Mongoose membutuhkan 262 baris untuk dataset besar kami, Prisma menyelesaikannya hanya dalam 221 baris.
  • Dilengkapi dengan alat CLI yang menyederhanakan pembuatan dan migrasi basis data, yang sejauh ini merupakan yang terbaik yang pernah saya lihat dari sebuah ORM, meskipun belum sempurna.
  • Mendukung kueri SQL mentah, menawarkan fleksibilitas saat dibutuhkan.
  • Sintaks kode bersih dan lebih mudah dipahami dibandingkan Sequelize, sehingga lebih mudah dipelajari.
  • Secara otomatis menghasilkan query builder untuk Node.js dan TypeScript melalui kliennya, yang merupakan sentuhan yang bagus.
  • Memiliki dokumentasi yang sangat baik dan rapi. ChatGPT tidak se-update Prisma, tetapi dokumentasi resmi sering kali menutup kekurangannya.
  • Statistik komunitas per 15 Mei 2023: Di NPM, terakhir diperbarui 6 hari yang lalu dengan 1.344.705 unduhan mingguan; di GitHub, terakhir diperbarui 3 jam yang lalu dengan 1,1k Fork dan 31,3k Bintang.

Kekurangan Prisma:

  • Tidak mendukung penyaringan Regex untuk Postgres, meskipun menawarkan alternatif seperti “contains,” “includes,” dan “startsWith.”
  • Performa menjadi masalah besar dalam pengujian saya. Membuat entri untuk dataset besar kami membutuhkan sekitar 11,21 detik per entri di Prisma dibandingkan 2,26 detik di Sequelize, kira-kira 5x lebih lambat.
  • Menghapus satu entri dari dataset besar membutuhkan hampir 4 menit, yang menjadi alasan pembatalan bagi kebutuhan kami.
  • Bahkan dengan perbandingan yang adil pada dataset relasi tiga lapis yang kompleks, Sequelize secara signifikan lebih cepat dalam penghapusan.
  • Prisma didukung oleh startup dengan pendanaan sebesar $56,5 juta. Meskipun kode ORM utamanya bersifat sumber terbuka di bawah Apache-2.0, saya waspada terhadap potensi perubahan lisensi di kemudian hari, mirip dengan apa yang terjadi pada MongoDB.

Perbandingan terperinci ini membuat jelas bahwa Sequelize lebih selaras dengan kebutuhan STMS, terutama dalam hal performa dan keandalan jangka panjang. Tetapi saya pikir menguraikannya seperti ini mungkin akan membantu orang lain yang bergulat dengan pilihan yang sama untuk proyek mereka.

Proses Migrasi

Transformasi Struktur Data

Mengonversi dari struktur dokumen MongoDB ke struktur relasional Postgres memerlukan perencanaan yang cermat. Saya harus:

  1. Menganalisis Relasi: Mengidentifikasi bagaimana dokumen MongoDB saling berhubungan dan merancang relasi kunci asing yang sesuai
  2. Menormalkan Data: Memecah dokumen bertingkat menjadi tabel-tabel terpisah jika sesuai
  3. Mempertahankan Fitur JSON: Menggunakan kolom JSONB untuk data yang benar-benar tidak terstruktur yang perlu tetap fleksibel
  4. Merancang Indeks: Membuat indeks yang sesuai untuk performa kueri

Solusi Kustom

Migrasi ini memerlukan pengembangan beberapa solusi kustom:

1. Skrip Migrasi Data Saya membuat skrip komprehensif untuk:

  • Mengekstrak data dari koleksi MongoDB
  • Mengubah struktur dokumen ke format relasional
  • Mengimpor data ke tabel Postgres dengan relasi yang tepat

2. Lapisan Kompatibilitas API Untuk mempertahankan tanpa waktu henti, saya membangun lapisan kompatibilitas yang dapat:

  • Meneruskan permintaan ke MongoDB atau Postgres tergantung status migrasi
  • Memastikan konsistensi data selama periode transisi
  • Menyediakan mekanisme cadangan

3. Middleware Kustom Mengembangkan middleware untuk menangani perbedaan dalam cara MongoDB dan Postgres menangani operasi tertentu, memastikan endpoint API yang ada terus berfungsi tanpa modifikasi.

Mengatasi Tantangan Teknis

Menangani Relasi Kompleks

Salah satu tantangan terbesar adalah mengonversi dokumen tertanam MongoDB menjadi relasi Postgres. Misalnya, satu dokumen MongoDB mungkin berisi:

  • Properti dasar
  • Objek bertingkat yang mewakili entitas terkait
  • Array dokumen tertanam

Ini harus diuraikan dengan hati-hati menjadi:

  • Tabel utama untuk entitas utama
  • Tabel penghubung untuk relasi banyak-ke-banyak
  • Relasi kunci asing untuk asosiasi satu-ke-banyak

Optimisasi Kueri

Pola kueri MongoDB tidak secara langsung diterjemahkan ke SQL. Saya harus:

  • Menulis ulang pipeline agregasi kompleks sebagai join SQL
  • Mengoptimalkan indeks untuk pola kueri baru
  • Memastikan performa kueri memenuhi atau melampaui performa MongoDB

Integritas Data

Memastikan integritas data selama migrasi memerlukan:

  • Skrip validasi komprehensif
  • Prosedur rollback
  • Sinkronisasi data waktu nyata selama periode transisi

Hasil & Dampak

Migrasi STMS dari MongoDB ke Postgres berhasil diselesaikan tanpa waktu henti sambil mempertahankan hampir semua fitur dan fungsionalitas. Hasilnya melampaui ekspektasi:

Peningkatan Kinerja:

  • Performa kueri meningkat untuk kueri relasional yang kompleks
  • Konsistensi dan integritas data yang lebih baik
  • Pemanfaatan penyimpanan yang lebih efisien

Manfaat Operasional:

  • Kemampuan pemantauan dan debugging yang ditingkatkan
  • Integrasi yang lebih baik dengan alat berbasis SQL yang sudah ada di eBay
  • Prosedur pencadangan dan pemulihan yang lebih baik

Dampak pada Tim:

  • Peningkatan pengetahuan tim tentang basis data relasional
  • Menetapkan pola untuk migrasi basis data di masa depan
  • Membuat alat dan proses yang dapat digunakan kembali

Keterampilan Teknis yang Diperoleh

Proyek ini secara signifikan memperluas keahlian teknis saya:

Teknologi Basis Data:

  • Pemahaman mendalam tentang fitur dan optimisasi Postgres
  • Optimisasi kueri SQL dan penyetelan performa
  • Pola desain basis data dan normalisasi
  • Konfigurasi basis data primary-standby

Alat Pengembangan:

  • ORM Sequelize dan pembuatan kueri
  • Strategi migrasi basis data
  • Metodologi pengujian performa
  • Validasi data dan pemeriksaan integritas

Pola Arsitektur:

  • Strategi migrasi tanpa waktu henti
  • Lapisan kompatibilitas API
  • Pola abstraksi basis data
  • Sistem pemantauan dan peringatan

Pertumbuhan Pribadi & Profesional

Proyek migrasi ini bersifat transformatif bagi pengembangan karier saya. Proyek ini mendorong saya ke wilayah yang belum saya jelajahi, menuntut:

Keterampilan Kepemimpinan:

  • Memimpin proyek teknis yang kompleks tanpa pengalaman sebelumnya
  • Mengambil keputusan arsitektural penting di bawah tekanan
  • Berkoordinasi dengan berbagai tim dan pemangku kepentingan

Kemampuan Pemecahan Masalah:

  • Menguraikan masalah kompleks menjadi komponen yang dapat dikelola
  • Mengembangkan solusi kreatif untuk tantangan yang belum pernah terjadi sebelumnya
  • Menyeimbangkan berbagai persyaratan dan kendala yang saling bersaing

Komunikasi & Kerja Tim:

  • Menjelaskan konsep teknis kepada pemangku kepentingan non-teknis
  • Mendokumentasikan proses dan keputusan untuk referensi di masa depan
  • Membimbing anggota tim tentang teknologi dan pola baru

Pelajaran yang Dipetik

Pelajaran Teknis

  1. Pemilihan Basis Data Itu Penting: Pilihan antara NoSQL dan SQL harus didasarkan pada kasus penggunaan spesifik dan persyaratan jangka panjang
  2. Pengujian Performa Itu Kritis: Keunggulan teoritis tidak selalu diterjemahkan menjadi peningkatan performa di dunia nyata
  3. Perencanaan Migrasi: Perencanaan dan pengujian yang komprehensif sangat penting untuk migrasi yang kompleks
  4. Investasi pada Tooling: Membangun tooling yang tepat sejak awal menghemat banyak waktu dan mengurangi kesalahan

Pelajaran Manajemen Proyek

  1. Komunikasi dengan Pemangku Kepentingan: Pembaruan rutin dan komunikasi yang jelas mencegah kesalahpahaman
  2. Manajemen Risiko: Memiliki rencana cadangan dan prosedur rollback sangat penting
  3. Manajemen Waktu: Sisakan waktu buffer untuk tantangan tak terduga dan kurva pembelajaran
  4. Dokumentasi: Dokumentasi yang menyeluruh memungkinkan transfer pengetahuan dan pemeliharaan di masa depan

Kesimpulan

Migrasi STMS dari MongoDB ke Postgres berdiri sebagai masalah teknis paling menantang dan paling memuaskan yang pernah saya selesaikan dalam karier saya. Ini menuntut bukan hanya keahlian teknis, tetapi juga kepemimpinan, perencanaan, dan kemampuan beradaptasi. Keberhasilan proyek ini menunjukkan bahwa dengan perencanaan yang tepat, pengujian yang menyeluruh, dan komitmen terhadap keunggulan, bahkan tantangan teknis yang paling kompleks pun dapat diatasi.

Pengalaman ini secara fundamental mengubah pendekatan saya terhadap rekayasa perangkat lunak, menekankan pentingnya:

  • Memahami konteks dan persyaratan secara menyeluruh sebelum membuat keputusan teknis
  • Menginvestasikan waktu pada tooling dan pengujian yang tepat
  • Menjaga komunikasi yang jelas sepanjang proyek yang kompleks
  • Bersedia mempelajari teknologi dan pendekatan baru saat diperlukan

Keberhasilan migrasi ini tidak hanya meningkatkan kemampuan STMS tetapi juga menetapkan pola dan proses yang terus memberi manfaat bagi proyek infrastruktur eBay. Ini memperkuat keyakinan saya bahwa menerima tantangan yang belum diketahui dan berhasil melaluinya adalah kunci bagi perkembangan pribadi dan profesional.

Menengok ke belakang, proyek ini merupakan titik balik dalam karier saya, mengubah saya dari seorang pengembang yang menerapkan solusi menjadi seorang insinyur yang dapat merancang dan memimpin inisiatif teknis yang kompleks. Kepercayaan diri dan keterampilan yang diperoleh dari pengalaman ini terus memandu pendekatan saya terhadap tantangan dan peluang baru dalam rekayasa perangkat lunak.