MongoDB إلى Postgres

🚨 هذه المقالة هي دمج بين MongoDB إلى Postgres (2024-03-06) و Sequelize مقابل Prisma (2023-05-25). تم حذف المدونات الأصلية، وقد حلت هذه المدونة محلها لأن كلاهما كان يحتوي أساسًا على نفس المحتوى/المعلومات. بدأ الترحيل في أوائل مارس 2023، وتم التحويل في منتصف نوفمبر 2023، وتم إغلاق جميع نسخ نظام MongoDB القديم بالكامل في أوائل يناير 2024.

المقدمة

خلال فترة عملي في eBay، واجهت ما أصبح أصعب مشكلة تقنية في مسيرتي: ترحيل نظام إدارة التخزين (STMS) من MongoDB إلى Postgres. لم يكن هذا مجرد تبديل بسيط لقاعدة البيانات؛ بل كان تحولًا معماريًا كاملاً لنظام حيوي يستقبل أكثر من 1.5 مليون مقياس في الدقيقة عبر مراكز بيانات eBay، مع شرط عدم وجود أي توقف والحفاظ على تقريبًا جميع الوظائف الحالية.

ما هو STMS؟

نظام إدارة التخزين (STMS) يعمل كأداة داخلية حيوية لفريق البنية التحتية للخدمات والتخزين (SSI) في eBay. يراقب ويدير الأجهزة عبر مراكز بيانات eBay، مما يتيح للمهندسين:

  • مراقبة المقاييس من العشرات من المصفوفات، المفاتيح، المضيفين، مجموعات الأقراص، والعنقودات
  • التعامل مع التنبيهات للمفاتيح والمصفوفات
  • إكمال مهام متقدمة مثل تخصيص المضيفين
  • الوصول إلى البيانات في الوقت الحقيقي للخدمات الداخلية الأخرى في eBay

يضم STMS أكثر من 70 مصفوفة، 60 مفتاحًا، 1100 مضيف، 900 مجموعة أقراص، و200 عنقود عبر 3 من مراكز بيانات eBay. نظرًا لدوره الحيوي في بنية eBay التحتية، فإن أي توقف أو فقدان للوظائف سيؤثر مباشرة على الخدمات الأساسية للشركة وعملياتها التجارية.

التحدي

لماذا كان الترحيل ضروريًا

لم يُتخذ قرار الترحيل من MongoDB إلى Postgres بخفة. بينما خدم MongoDB نظام STMS جيدًا في البداية، فإن التعقيد المتزايد لعلاقات بياناتنا والحاجة إلى قدرات استعلام أكثر تطورًا جعلت Postgres حلاً أفضل على المدى الطويل لحالتنا.

ما الذي جعل هذه المشكلة صعبة

نشأت تعقيدات هذا الترحيل من عدة تحديات أساسية:

1. اختلافات أساسية بين قواعد البيانات
MongoDB وPostgres هما قواعد بيانات مختلفة جوهريًا. MongoDB هي قاعدة بيانات مستندة إلى المستندات (NoSQL)، مما يعني أن البيانات تُخزن كـ JSON في مجموعات، مثل المستندات في خزانة ملفات. Postgres هي قاعدة بيانات علائقية (SQL)، مما يعني أن البيانات تُخزن كصفوف في جداول، مثل جدول بيانات.

2. بنية قاعدة الشيفرة
تم بناء الواجهة الخلفية بالكامل لنظام STMS لمعالجة وإدارة البيانات كـ JSONs، باستخدام حزم متوافقة حصريًا مع MongoDB لعمليات قاعدة البيانات. هذا يعني ليس مجرد تغيير قاعدة البيانات، بل إعادة هيكلة طريقة تعامل تطبيقنا بالكامل مع البيانات.

3. متطلبات عدم وجود توقف
نظرًا لأهمية STMS كأداة داخلية، لا يمكن أن يكون هناك أي توقف أثناء الترحيل. كان على النظام الاستمرار في تقديم أكثر من 1.5 مليون مقياس في الدقيقة طوال العملية بأكملها.

4. جدول زمني ضيق وخبرة محدودة
كان يجب إكمال الترحيل خلال بضعة أشهر، دون وجود خطة تنفيذ واضحة في البداية. لا أنا ولا زملائي كنا نمتلك خبرة في ترحيل قاعدة شيفرة قديمة كبيرة من قواعد NoSQL إلى قواعد SQL، وكان لدي خبرة محدودة سابقة مع Postgres.

5. النطاق والتعقيد
شمل الترحيل تحويل 36 مجموعة MongoDB إلى 74 جدول Postgres، مما استلزم اعتبارًا دقيقًا للعلاقات، والفهرسة، وتحسين الاستعلامات.

اختيار ORM المناسب: Sequelize مقابل Prisma

كان أحد أولى القرارات الكبيرة اختيار أداة ORM (تخطيط الكائنات العلائقية). نظرًا لأن قاعدة شيفرتنا كانت مصممة بالفعل لاستخدام Mongoose مع MongoDB، فإن استخدام ORM سيوفر أنسب مسار للانتقال.

تحليل المتطلبات

بعد تحليل دقيق لاحتياجات المشروع، وضعت معايير أساسية لأي حل ORM:

  • يجب أن يكون حزمة JavaScript (معظم شيفرتنا مكتوبة بـ JavaScript)
  • يجب أن يدعم Postgres ومعظم ميزاته
  • يجب أن تكون الأداء على الأقل مساوية أو أفضل من Mongoose
  • يجب أن يكون مفتوح المصدر ومُصان

المتنافسون

بعد بحث مكثف، قمت بتضييق الاختيارات إلى متنافسين رئيسيين: Sequelize وPrisma. أنشأت بيئات اختبار شاملة باستخدام Docker لـ Postgres وحولت أكبر مجموعة بيانات لدينا، الأكثر تعقيدًا، من بنية المستندات إلى بنية الجداول.

منهجية الاختبار

لكل ORM، قمت بقياس الأداء عبر عمليات حاسمة:

  • الوقت لإنشاء سجل
  • الوقت لتحديث سجل
  • الوقت لتحديث سجلات متداخلة (العلاقات وقيم مفاتيح JSON)
  • الوقت لحذف سجل
  • الوقت لاستعلام/جلب سجل

القرار: Sequelize

حوالي 15 مايو 2023، قررت أن Sequelize هو ORM الأفضل لحالتنا. إليكم السبب:

مزايا Sequelize:

  • مفتوح المصدر حقًا وليس مُدارًا من قبل شركة ناشئة ممولة
  • يدعم معظم ميزات Postgres
  • أداء أفضل، خاصة مقارنةً بـ Prisma
  • نظام بيئي ناضج مع أكثر من 10 سنوات من التطوير
  • تمثيل مرن للنماذج/المخططات باستخدام فئات JavaScript
  • دعم للانضمامات المعقدة وخيارات التصفية بما في ذلك Regex

نتائج الأداء:

في اختباراتي، تفوق Sequelize بشكل كبير على Prisma. بالنسبة لسجلات مجموعة البيانات الكبيرة لدينا:

  • Sequelize: ~2.26 ثانية لكل سجل
  • Prisma: ~11.21 ثانية لكل سجل

كان Prisma أبطأ بحوالي 5 مرات مقارنةً بـ Sequelize لحالتنا. بالإضافة إلى ذلك، استغرق حذف سجل واحد من أكبر مجموعة بيانات لدينا ما يقرب من 4 دقائق باستخدام Prisma، وهو أمر غير مقبول لمتطلباتنا.

تحديات Sequelize:

  • تمثيلات نماذج أكثر تعقيدًا وممتلئة (564 سطرًا مقابل 262 سطرًا لـ Mongoose)
  • بناء جملة مربك في بعض الحالات
  • تعقيد ترحيل قاعدة البيانات
  • توثيق أقل شمولًا مقارنةً بـ Prisma

مقارنة الإيجابيات والسلبيات بين Sequelize وPrisma

لتقديم صورة أوضح عن سبب اختياري Sequelize، أرغب في مشاركة الإيجابيات والسلبيات المفصلة التي جمعتها لكلا ORM خلال تقييمي. كما نظرت إلى كيفية مقارنتهما من حيث تمثيل المخطط ودعم المجتمع اعتبارًا من 15 مايو 2023. ساعد هذا التحليل العميق في تثبيت اختياري، وآمل أن يكون مفيدًا لأي شخص آخر يواجه قرارًا مشابهًا.

إيجابيات Sequelize:

  • يحتوي على دالة sync() التي تنشئ وتدير الجداول تلقائيًا، مما يوفر جهدًا يدويًا كبيرًا.
  • يمكنه التعامل مع الانضمامات المعقدة للبيانات المتداخلة، وهو أمر حاسم لبنية STMS.
  • يدعم مجموعة واسعة من خيارات التصفية، بما في ذلك Regex، مما يمنح مرونة في الاستعلامات.
  • تم تمثيل النموذج/المخطط في JavaScript الخام باستخدام الفئات، والتي يمكن تخصيصها بشكل كبير لتلبية الاحتياجات المحددة.
  • يتعامل مع اتصالات قاعدة البيانات بسلاسة، بما في ذلك دعم اتصالات قراءة متعددة.
  • يدعم استعلامات SQL الخام عندما تحتاج إلى الغوص في التفاصيل.
  • إحصائيات المجتمع اعتبارًا من 15 مايو 2023: على NPM، آخر تحديث قبل 14 يومًا مع 1,505,835 تحميل أسبوعيًا؛ على GitHub، آخر تحديث أمس مع 4.2k Forks و27.9k Stars. كان مفتوح المصدر برخصة MIT لأكثر من 10 سنوات، لذا أنا واثق من استمراره.

سلبيات Sequelize:

  • يمكن أن يصبح تمثيل النموذج/المخطط معقدًا وممتلئًا جدًا. على سبيل المثال، كان تمثيل Mongoose لمجموعة البيانات الكبيرة لدينا حوالي 262 سطرًا (بما في ذلك الفراغات)، بينما تضخم نفس مجموعة البيانات في Sequelize إلى 564 سطرًا.
  • يمكن أن يكون البناء الجملة مربكًا ومعقدًا في بعض السيناريوهات، مما أبطأني أحيانًا.
  • ترحيل أو تعديل قاعدة البيانات أمر مزعج. حتى مع sequelize-cli الذي يولد سكريبتات الترحيل، لا يزال الأمر مرهقًا، رغم أنني لاحظت أن هذه نقطة ألم شائعة مع معظم ORM.
  • التوثيق ليس رائعًا، رغم أنه يتحسن. لحسن الحظ، أدوات مثل ChatGPT لديها فهم قوي لـ Sequelize بفضل تاريخها الطويل، مما ساعد في سد الفجوات.
  • ليس حساسًا للنوع كما هو Prisma، مما قد يؤدي إلى مشكلات في بعض المشاريع.
  • دعم TypeScript محدود، رغم أن هذا لم يكن مصدر قلق لـ STMS، لكنه قد يكون عاملًا حاسمًا للآخرين.

إيجابيات Prisma:

  • يستخدم لغة مخطط خاصة به، مما يجعل إنشاء النموذج أنظف وأكثر اختصارًا. للمقارنة، استغرق Mongoose 262 سطرًا لمجموعة البيانات الكبيرة، بينما أنجز Prisma ذلك في 221 سطرًا فقط.
  • يأتي بأداة CLI تُبسط إنشاء قاعدة البيانات والترحيل، وهي الأفضل التي رأيتها من ORM حتى الآن، حتى وإن لم تكن مثالية.
  • يدعم استعلامات SQL الخام، مما يوفر مرونة عند الحاجة.
  • بناء الكود نظيف وأبسط للفهم مقارنةً بـ Sequelize، مما يجعله أسهل للتعلم.
  • ينتج تلقائيًا منشئي استعلامات لـ Node.js وTypeScript عبر عميله، وهو لمسة لطيفة.
  • يحتوي على توثيق ممتاز ونظيف. لا يمتلك ChatGPT أحدث المعلومات عن Prisma، لكن الوثائق الرسمية تعوض ذلك غالبًا.
  • إحصائيات المجتمع اعتبارًا من 15 مايو 2023: على NPM، آخر تحديث قبل 6 أيام مع 1,344,705 تحميل أسبوعيًا؛ على GitHub، آخر تحديث قبل 3 ساعات مع 1.1k Forks و31.3k Stars.

سلبيات Prisma:

  • لا يدعم تصفية Regex لـ Postgres، رغم أنه يقدم بدائل مثل “contains” و"includes" و"startsWith".
  • كان الأداء مشكلة رئيسية في اختباراتي. استغرق إنشاء سجلات لمجموعة البيانات الكبيرة حوالي 11.21 ثانية لكل سجل في Prisma مقارنةً بـ 2.26 ثانية في Sequelize، أي أبطأ بحوالي 5 مرات.
  • استغرق حذف سجل واحد من مجموعة البيانات الكبيرة ما يقرب من 4 دقائق، وهو ما كان غير مقبول لاحتياجاتنا.
  • حتى مع مقارنة عادلة على مجموعة بيانات معقدة ذات علاقات ثلاثية الطبقات، كان Sequelize أسرع بكثير في عمليات الحذف.
  • يتم دعم Prisma من قبل شركة ناشئة تمولها 56.5 مليون دولار. بينما الكود الرئيسي لـ ORM مفتوح المصدر تحت رخصة Apache-2.0، فأنا أحذر من تغييرات الترخيص المحتملة في المستقبل، مشابهة لما حدث مع MongoDB.

أظهرت هذه المقارنات التفصيلية أن Sequelize يتماشى بشكل أفضل مع احتياجات STMS، خاصةً من حيث الأداء والموثوقية على المدى الطويل. لكنني اعتقدت أن تفصيل ذلك قد يساعد الآخرين الذين يواجهون نفس الاختيار لمشاريعهم.

عملية الترحيل

تحويل بنية البيانات

تحويل بنية المستندات في MongoDB إلى بنية علاقية في Postgres تطلب تخطيطًا دقيقًا. كان عليّ:

  1. تحليل العلاقات: تحديد كيفية ارتباط مستندات MongoDB ببعضها البعض وتصميم علاقات المفاتيح الأجنبية المناسبة
  2. تطبيع البيانات: تفكيك المستندات المتداخلة إلى جداول منفصلة حيثما كان ذلك مناسبًا
  3. الحفاظ على ميزات JSON: استخدام أعمدة JSONB للبيانات غير المهيكلة حقًا والتي تحتاج إلى البقاء مرنة
  4. تصميم الفهارس: إنشاء فهارس مناسبة لأداء الاستعلامات

حلول مخصصة

تطلبت عملية الترحيل تطوير عدة حلول مخصصة:

1. سكريبتات ترحيل البيانات
قمت بإنشاء سكريبتات شاملة لـ:

  • استخراج البيانات من مجموعات MongoDB
  • تحويل بنية المستندات إلى صيغة علاقية
  • استيراد البيانات إلى جداول Postgres مع العلاقات الصحيحة

2. طبقة توافقية لواجهة برمجة التطبيقات (API)
للحفاظ على عدم وجود توقف، بنيت طبقة توافقية يمكنها:

  • توجيه الطلبات إما إلى MongoDB أو إلى Postgres حسب حالة الترحيل
  • ضمان اتساق البيانات خلال فترة الانتقال
  • توفير آليات احتياطية

3. وسائط مخصصة
قمت بتطوير وسائط لمعالجة الاختلافات في طريقة تعامل MongoDB وPostgres مع بعض العمليات، مما يضمن استمرار عمل نقاط النهاية في API دون تعديل.

التغلب على التحديات التقنية

التعامل مع العلاقات المعقدة

كان أحد أكبر التحديات هو تحويل المستندات المتضمنة في MongoDB إلى علاقات في Postgres. على سبيل المثال، قد يحتوي مستند MongoDB واحد على:

  • خصائص أساسية
  • كائنات متداخلة تمثل كيانات مرتبطة
  • مصفوفات من المستندات المتضمنة

كان يجب تفكيك ذلك بعناية إلى:

  • جداول رئيسية للكيانات الأساسية
  • جداول وصل للعلاقات many-to-many
  • علاقات مفاتيح أجنبية للارتباطات one-to-many

تحسين الاستعلامات

أنماط استعلامات MongoDB لا تُترجم مباشرة إلى SQL. كان عليّ:

  • إعادة كتابة خطوط التجميع المعقدة كعمليات ربط (joins) في SQL
  • تحسين الفهارس لأنماط الاستعلامات الجديدة
  • التأكد من أن أداء الاستعلامات يفي أو يتجاوز أداء MongoDB

سلامة البيانات

تطلب ضمان سلامة البيانات أثناء الترحيل:

  • سكريبتات تحقق شاملة
  • إجراءات استعادة (rollback)
  • مزامنة بيانات في الوقت الحقيقي خلال فترات الانتقال

النتائج والأثر

اكتمل ترحيل STMS من MongoDB إلى Postgres بنجاح دون أي توقف، مع الحفاظ على تقريبًا جميع الميزات والوظائف. تجاوزت النتائج التوقعات:

تحسينات الأداء:

  • تحسن أداء الاستعلامات للqueries العلائقية المعقدة
  • تحسين اتساق البيانات وسلامتها
  • استغلال أكثر كفاءة للتخزين

الفوائد التشغيلية:

  • تعزيز قدرات المراقبة وتصحيح الأخطاء
  • تحسين التكامل مع أدوات eBay القائمة على SQL
  • تحسين إجراءات النسخ الاحتياطي والاستعادة

أثر الفريق:

  • تعزيز معرفة الفريق بقاعدة البيانات العلائقية
  • وضع نماذج للترحيلات المستقبلية لقواعد البيانات
  • إنشاء أدوات وعمليات قابلة لإعادة الاستخدام

المهارات التقنية المكتسبة

وسّع هذا المشروع خبرتي التقنية بشكل كبير:

تقنيات قواعد البيانات:

  • فهم عميق لميزات Postgres وتحسينها
  • تحسين استعلامات SQL وضبط الأداء
  • نماذج تصميم قواعد البيانات وتطبيعها
  • تكوينات قاعدة البيانات الأساسية-الاحتياطية

أدوات التطوير:

  • Sequelize ORM وبناء الاستعلامات
  • استراتيجيات ترحيل قواعد البيانات
  • منهجيات اختبار الأداء
  • التحقق من صحة البيانات وفحص سلامتها

أنماط الهندسة المعمارية:

  • استراتيجيات ترحيل بدون توقف
  • طبقات توافقية لواجهة برمجة التطبيقات
  • أنماط تجريد قاعدة البيانات
  • أنظمة المراقبة والتنبيه

النمو الشخصي والمهني

كان هذا المشروع التحويلي لتطوير مسيرتي المهنية. دفعني إلى مناطق غير مألوفة، متطلبًا:

مهارات القيادة:

  • قيادة مشروع تقني معقد دون خبرة سابقة
  • اتخاذ قرارات معمارية حاسمة تحت الضغط
  • التنسيق مع فرق متعددة وأصحاب مصلحة

قدرات حل المشكلات:

  • تفكيك المشكلات المعقدة إلى مكونات قابلة للإدارة
  • تطوير حلول إبداعية لتحديات غير مسبوقة
  • موازنة متطلبات وقيود متنافسة متعددة

الاتصال والعمل الجماعي:

  • شرح المفاهيم التقنية لأصحاب المصلحة غير التقنيين
  • توثيق العمليات والقرارات للرجوع إليها مستقبلاً
  • إرشاد أعضاء الفريق إلى تقنيات وأنماط جديدة

الدروس المستفادة

دروس تقنية

  1. اختيار قاعدة البيانات مهم: يجب أن يكون الاختيار بين NoSQL وSQL مبنيًا على حالات الاستخدام المحددة والمتطلبات طويلة الأجل
  2. اختبار الأداء أمر حاسم: لا تتحول المزايا النظرية دائمًا إلى تحسينات أداء في الواقع
  3. تخطيط الترحيل: التخطيط والاختبار الشاملان ضروريان للترحيلات المعقدة
  4. الاستثمار في الأدوات: بناء أدوات مناسبة في البداية يوفر وقتًا كبيرًا ويقلل الأخطاء

دروس إدارة المشروع

  1. الاتصال بأصحاب المصلحة: التحديثات المنتظمة والاتصال الواضح يمنعان سوء الفهم
  2. إدارة المخاطر: وجود خطط احتياطية وإجراءات استعادة أمر أساسي
  3. إدارة الجدول الزمني: تخصيص وقت احتياطي للتحديات غير المتوقعة ومنحنيات التعلم
  4. التوثيق: التوثيق الشامل يتيح نقل المعرفة وصيانة المستقبل

الخلاصة

يُعد ترحيل STMS من MongoDB إلى Postgres أكثر مشكلة تقنية تحديًا ومكافأةً حلّتها في مسيرتي المهنية. لم يتطلب ذلك فقط خبرة تقنية، بل أيضًا قيادة، تخطيط، وتكيف. أظهر نجاح المشروع أنه من خلال التخطيط السليم، الاختبار الدقيق، والالتزام بالتميز، يمكن التغلب على أصعب التحديات التقنية.

غيّر هذا التجربة نهجي في هندسة البرمجيات، مؤكدًا أهمية:

  • فهم السياق الكامل والمتطلبات قبل اتخاذ القرارات التقنية
  • استثمار الوقت في الأدوات والاختبارات المناسبة
  • الحفاظ على اتصال واضح طوال المشاريع المعقدة
  • الاستعداد لتعلم تقنيات ونهج جديدة عند الحاجة

نجاح الترحيل لم يحسن فقط قدرات STMS بل وضع نماذج وعمليات تستمر في إفادة مشاريع بنية تحتية في eBay. عزز إيماني بأن احتضان التحديات غير المعروفة والنجاح فيها هو المفتاح للنمو الشخصي والمهني.

عند النظر إلى الوراء، يمثل هذا المشروع نقطة تحول في مسيرتي، محولًا إياي من مطور ينفذ حلولًا إلى مهندس يستطيع تصميم وقيادة مبادرات تقنية معقدة. لا تزال الثقة والمهارات المكتسبة من هذه التجربة توجه نهجي تجاه التحديات والفرص الجديدة في هندسة البرمجيات.