بمقالنا التالت من سلسلة How to be a better Back End Engineer رح نتطرق لموضوع كتير أساسي و كتير مهم سواء اتكلمنا على scale صغير 10 و 20 مستخدم ، أو طلعنا لحجم ال 1M و 10M مستخدم ، و هو ال Database Design. و لكبر و تفرع الموضوع ، رح يكون مقالنا مقسم ﻷكتر من جزء بكل جزء رح نفصل موضوعنا من ناحية معينة ، و بكل جزء رح نتطرق لمواضيعنا من منظور ال Relational Databases و ال Non-relational Databases لنغطي الحالتين مع بعض ، فبتمنى تستفيدو من المقال ✨

الجزء الأول ، أسس و تصميم البيانات (Data modeling and ACID principles):-

قبل ما نبدأ بمرحلة انشاء ال tables أو ال documents بالداتابيز اللي عندنا ، لازم نكون حاطين بعين الاعتبار انو ال Data Entities اللي حنعتمد عليها بعمليات ال I/O أثناء عمل نظامنا ، معمولة بصورة efficient بما بكفي انها ما تكون bottle neck في النظام من نواحي كثيرة مثل: الداتا المتحصل عليها من عمليات ال read ما بتحتاج تمر بعمليها فلترة أو تصحيح أو تعديل كتيرة لدرجة تضيف overhead على السيستم اللي عندي - عملية ال read ذات نفسا ما تكون expensive على الموارد اللي عندي ، بعني ما تطلب مني compute عالي أو memory كبيرة لاتمام العملية - ال Data entities نفسهم قابلين للتعديل بصورة معقولة تمكن السيستم اللي عندي من أنو يكبر أو بعبارة اقصر و أوضح ، ما تعرقل ال system scalability في المستقبل - ….. و غيرا كتير من ال design concerns اللي لازم ناخدا بعين الاعتبار أثناء تصميم ال Data Entities اللي حاستخدمهم بشغلي على السيستم.

و غالبا ، من هالمرحلة بيتحدد عندي رح اشتغل ب Relational/Non-relational Database من خلال تحديد الأسس اللي بيحتاجا نظامنا ، مثال على هالمرحلة الاتي:

مقارنة ACID vs BASE:

كما ذكرنا فوق ، تحديد النقاط اللي لازم نظامنا يمشي عليها مثل geographical scale ، availability constraints ، data consistency ، و غيرا من المواصفات اللي بنحددا أثناء تصميم أي سيستم ، بيقودنا الى ال principles الأنسب لعملنا ، و بالتالي نوع الداتابيز الأنسب ، و بالتالي طريقة تصميم ال data entities اﻷنسب.

في ما يلي ، رح نتطرق لل ACID principles و ال BASE principles و نشوف الفرق بينهم و أنواع الداتابيز الأنسب لكل واحد.

ال ACID principles ، و بالتحديد مصطلح ACID ، هو اختصار للاتي:

اولا Atomicity: هي قاعدة أن نجاح أي عملية بتتم في السيستم مربوط بنجاح جميييع مراحل العملية ، و فشل أي مرحلة بيوجب التراجع عن أي تعديلات تمت من باقي العمليات. و مثال على هالشي معاملات التحويلات البنكية ، اذا كانت المراحل هي خصم المبلغ  -> تحويل المبلغ -> اضافة المبلغ ، و اي وحدة من الخطوات فشلت ، فلازم باقي الخطوات تتلغي حالا و تتلغي معها التعديلات اللي عملتا.

ثانيا Consistency: ال Consistency في ال ACID rules بالتحديد بتعني أن أي تعديل بتم داخل السيستم لاااازم يتم وفقا لل constraints المعرفة داخل السيستم ، يعني ، أن اذا وحدة من ال Data entities كانت معرفة على أنها بتحتوي على 6 attributes هم name, age, phone, email, password, date-of-birth و كانت صيغة ال date-of-birth محددة بشكل معين مثلا YYYY/MM/DD و حاولت وحدة من عمليات ال write تدخل data entity ال date-of-birth فيها بصيغة DD/MM/YYYY. بالرغم من أنو الداتا صحيحة ، الا انها غير متوافقة مع ال constraints المتحددة في السيستم ، ف بالتالي بتم رفض العملية.

ثالثا Isolation: بغض النظر عن عدد عمليات ال I/O عندي بالسيستم ، و بغص النظر عن ال resources المطلوبة بكل عملية ، لازم كل عملية تتم على حدة من غير ما تأثر على عمل العمليات الأخرى ، ولا على نتائج العمليات الأخرى. مثال على هالشي ، أذا كان عندي أدمنين لقروب واتساب ، و الاتنين حبو يغيرو اسم القروب بنففففس اللحظة ، أي اسم رح يظهر في الأخير ؟ بهاد المثال بتحصل عملية isolation لكل عملية مع ال resources اللي بتحتاجا ، ثم بتم تنفيذ العملية ، ثم بتم اطلاق ال resources للعملية التالية لاستخداما ، و هكذا. بهالطريقة بنكون اتجنبنا ان يتم اخد ال resources الأساسية و استعمالا من غير ما تاخد بعين الاعتبار نتيجة العملية اللي سقتا ، و مثال اسم قروب ما ببين قدر الضرر اللي ممكن يسببو هالتداخل ، بس بحالات تانية متل اتمام عمليتين شراء في نفس اللحظة ، اذا تمت العمليتين بنفس اللحظة و الاتنين خصمو من الرصيد الاساسي من غير ما ياخدو بعين الاعتبار نتيجة العملية التانية ، بتقدرو تتخيلو حجم الضرر الناتج.

رابعا Durability: هاي النقطة بتركز اكتر شي على أنو الداتا اللي عندي ما تضيع في حال حصل crach out بالسيستم تبعي ، أو حصلت عملية migration اتسببت بضياع بعض البيانات أو ما الى هنالك من حوادث بتستهدف الداتابيز الخاصة بنطامنا. لهيك بنتبع سياسات ال periodic back ups و ال role back functions و استخدام ال inference أو ال hardware اللي بيضمن ال data consistency بهيك حالات.

و رح نلاحظ أن أغلب اذا ما كل الانظمة اللي بتتبع ال ACID principles بتطبقا على قواعد بيانات SQL أو الاسم الاصح Relational Databases ، بسبب أنو هالنوع من الداتابيز بيوفر الوسائل الجاهزة لتطبيق مفاهيم ال ACID مثل ال Atomicity (عن طريق ال Transactions) أو ال Consistency (عن طريق ال Keys و ال Constraints) و غيرا كتير وسائل لتحقيق ال ACID. كمان بنلاحظ ان الداتابيز بحالة ال ACID بتكون معدة لل Vertical Scaling اي انها ما بتعتمد على ال distribution بشكل أساسي.

أما في الكفة الاخرى عندنا ال BASE principles ، و اللي هي اختصار للاتي:

اولا Basically-Available: هو أنو يتحول اهتمامنا من أنو تكون عمليات ال Read دايما بتحمل اخر داتا تم حفظا في السيستم الى انو بس يكون عندي رد حتى في حال ما كان باحدث داتا عندي. يعني تحول اهتمامنا من يا اما Read بيعطيني رد بأحدث داتا يا أما مافي اي رد ، الى انو اي عملية Read لازم تعطيني رد بغض النظر كان رد بأحدث داتا أو لا. و مثال على هالشي مواقع ال E-Commerce اللي لازم فيها العميل على سبيل المثال في صفحة ال feed يحصل على المنتجات المتوفرة في المخزن حتى لو ما كانت الكميات محدثة باخر كميات بالمخزن ، المهم هو حصول العميل على رد.

ثانيا Soft-State: في الانظمة اللي بتتبع ال BASE principles ، بكون عندي السيستم موزع في اغلب الحالات على nodes متفرقة ، و عملية المزامنة ما بين ال nodes المتفرقة بتكون asynchronous ، أي ما بالضرورة تكون كل الداتا في كل ال nodes وصلت الى نفس ال state ، و هو شي يؤخذ في عين الاعتبار لما اتصمم السيستم لأول مرة ، أنو في حالات الداتا ما رح تكون موحدة ، بس عمل السيستم ما بيتأثر.

ثالثا Eventual Consistency: بما ان السيستم عندي بحالة ال BASE بيهتم بأنو السيستم يفضل up-and-running و ما مهم في توحيد ال state بين كل ال nodes ، ف الضمان الوحيد البكون مبني بطبيعة النظام أنو لو فضل السيستم سليم و من غير عمليات تعديل على ال state بأي وحدة من ال nodes لفترة كافية ، ف كل ال nodes رح توصل لنفس ال state بالأخير.

بنلاحظ كمان أن جميع الأنظمة أو أغلبا ، اللي بتتبع ال BASE principles ، بتميل لانها تستخدم قواعد بيانات No-SQL أو بالتسمية الأصح ، Non-relational Databases لسهولة التعامل و التعديل على ال data entities اللي فيها ، و كذلك عدم الحاجة لاستخدام أي اضافات مثل الconstraints أو transactions او غيرا من مميزات ال Relational Databases ، الشي اللي بيسهل التركيز على ادارة ال nodes المتعددة للسيستم و ضمان عملا و سرعتا ، و تصميم ال sync functions و ال fail over functions و غيرا من العمليات البتكون هدفا انها تحقق ال BASE principles.

كمان بنلاحظ متل ما ذكرنا فوق أنو بكون عندي node متفرقة كتير ، بسبب استخدام عملية ال Horizontal Scaling لتوفير عدد و كثافة ال nodes اللي بيتطلبا السيستم بمختلف ال Scales اللي ممكن يشتغل عليها.

رح نكتفي بهالقدر من التعمق بالجزء الأول من مقالنا الثالث ، Data modeling and ACID principles ، على أنو نكمل بالجزء القادم بموضوع مهم آخر هو Normalization rules vs Data Modeling Patterns

و اتمنى قراءة مفيدة للجميع ✨