+− THE DAILY DIFFdev & AI news
SHIP IT

نقلت Shopify حجوزات المخزون إلى MySQL

نقلت Shopify نظام حجز المخزون الخاص بها من Redis إلى قاعدة بيانات MySQL التي كانت تحتفظ بالفعل بسجل المخزون.

نقلت Shopify نظام حجز المخزون الخاص بها من Redis إلى قاعدة بيانات MySQL التي كانت تحتفظ بالفعل بسجل المخزون. تسمح مجموعة محدودة من صفوف الوحدات القابلة للقفل بشكل فردي لعمليات الدفع المتزامنة باستخدام SKIP LOCKED لتحديد وحدات مؤهلة مختلفة. يعتمد التصميم أيضًا على حدود المعاملات، وتخطيط المفتاح الأساسي، وقواعد التجديد، ومراقبة وقت الاحتفاظ بالاتصال عبر الدفع.

اقرأ النسخة المكتوبة (الإنجليزية) ↗

ما يغطيه هذا الفيديو

  • تعامل نموذج عداد الكمية القديم في Redis مع التزامن، لكن تنظيف الحجز وتحديث سجل MySQL لم يتمكنا من مشاركة معاملة ذرية محلية واحدة.
  • يستخدم البديل صفًا واحدًا لكل وحدة متاحة في مجموعة محدودة بحد أقصى 1000 لكل تركيبة صنف/موقع. يمكن أن تؤدي المجموعة الفارغة إلى تجديد مباشر مع طلبات متزامنة تنتظر خلف قفل التجديد.
  • المفتاح الأساسي المركب هو (shop_id, inventory_item_id, inventory_group_id, id). قللت Shopify من الحمل الزائد للقفل في نموذجها الأولي واستخدمت READ COMMITTED لتجنب أقفال الفجوة التي أعاقت التجديد.
  • تحذف الحجوزات صفوف المجموعة قبل إدخال سجلات الحجز. يؤدي الالتزام إلى تحرير أقفال قاعدة البيانات بينما يستمر الاحتفاظ المخزن عبر الدفع؛ المطالبة بالدفع الناجح للسجل وإزالة الحجز في معاملة ذرية لاحقة.
  • توثق MySQL SKIP LOCKED كعرض غير متناسق يتجاهل الصفوف المقفلة. ولا يؤسس عددًا كاملاً للمخزون أو تناوبًا عادلاً، وينطبق فقط على الأقفال على مستوى الصف وهو غير آمن للنسخ المتماثل القائم على العبارات.
  • يتضمن المثال المصدر expires_at، لكن Shopify لا توثق خوارزمية تنظيف انتهاء الصلاحية في MySQL. فرع الإصدار/انتهاء الصلاحية في الفيديو هو متطلب دورة حياة توضيحي.
  • كان وقت الاحتفاظ بالاتصال في رمز الدفع الآخر هو عنق الزجاجة النهائي للإنتاجية. قامت Shopify بكتابة كلا النظامين بشكل متوازي، وقارنت النتائج، وتحولت تدريجيًا مع خيار الرجوع إلى Redis.

النص المترجم

مترجم من السرد الإنجليزي الأصلي. يتم التحكم في الصوت والتعليقات التوضيحية المتاحة بواسطة YouTube.

لماذا نقل الحجوزات إلى MySQL؟

0:00 تحتاج عملية الدفع إلى Redis للبقاء سريعة. نقلت Shopify حجوزات المخزون إلى MySQL باستخدام صف واحد لكل وحدة في مجموعة محدودة. لماذا تختار MySQL؟ كيف تتخطى الأقفال بأمان؟ هذا هو The Daily Diff، من وراء الكواليس. ولماذا كانت الاستعلامات السريعة لا تزال تصل إلى سقف؟ Shopify هي منصة تجارة للبيع عبر الإنترنت والشخصي. Redis هو متجر بيانات في الذاكرة.

0:21 MySQL هي قاعدة بيانات علائقية، وقد احتفظت Shopify بالفعل بسجل المخزون الخاص بها هناك. يحتفظ الحجز بالمخزون لفترة وجيزة بينما يدفع المشتري.

لماذا كان وجود متجرين محفوفًا بالمخاطر؟

0:29 نموذج Redis الخاص بهم قلل من عداد العناصر. مطالبة طلب مدفوع تعني تحديث سجل MySQL وتنظيف Redis. يمكن أن تترك هذه الكتابات المنفصلة المخزون مباعًا مرتين أو غير متاح عندما يجب أن يكون قابلاً للبيع. يفتقر النموذج القديم أيضًا إلى الوعي بالموقع. يجب أن يختار البديل المخزون من مكان ما يمكنه تلبية الطلب. المستودع في القارة الخطأ يجعل إدخال قاعدة بيانات ممتازًا و وعد تسليم فظيعًا. استخدمت محاولات MySQL السابقة صف كمية، لذلك تجمعت عمليات الدفع المتنافسة عند

ما هي الوحدة القابلة للقفل؟

0:56 نفس القفل. فكر في حبل مخملي حول خلية جدول بيانات. إضافة المزيد من العمال يطيل فقط قائمة الانتظار. غيرت Shopify الكائن القابل للقفل. تحصل كل وحدة متاحة على صفها الخاص. قراءة قفل تتخطى الوحدات التي يحملها معاملة أخرى وتختار وحدات مؤهلة أخرى. يمكن للعمال المختلفين الحصول على صفوف مختلفة، بينما يظل العداد الساخن بعيدًا عن طريقهم.

ماذا يحدث عندما تفرغ المجموعة؟

1:15 هذه المجموعة محدودة بألف صف لكل عنصر وموقع. التجديد يسحب من السجل. إذا فرغ، فإن مسار الحجز يجدد مباشرًا، مع طلبات متنافسة تنتظر خلف قفل التجديد. المجموعة الفارغة لا تعني مستودعًا فارغًا. تحذف الحجوزات صفوف المجموعة المحددة، ثم تقوم بإدخال سجلات الحجز في معاملة. الالتزام يحرر أقفال قاعدة البيانات.

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

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

ماذا يغفل SKIP LOCKED؟

2:14 يتجاهل Skip locked الصفوف المقفلة، لذلك يسمي الدليل نتيجته عرضًا غير متناسق. لا يوفر عددًا كاملاً للمخزون ولا تناوبًا عادلاً. احتفظ بقرار التوفر وقواعد التجديد حوله.

أين كان السقف الحقيقي؟

2:26 وهذا السقف؟ كانت رموز الدفع الأخرى تحتفظ باتصالات قاعدة البيانات لفترة طويلة جدًا. قامت Shopify بوضع علامات على المتصلين وقياس وقت الاحتفاظ بالاتصال، ثم نظفت مسار الدفع وأعادت النظر في تزامن الخيوط. لا تزال الاستعلامات السريعة تنتظر في قائمة الانتظار خارج الاستعلام.

لماذا أشحن هذا التصميم؟

2:38 لقد قاموا بكتابة كلا النظامين بشكل متوازي مع Redis كسلطة، قارنوا النتائج، ثم تحولوا تدريجيًا مع مفتاح إيقاف. حكمي هو SHIP IT. سأشحن حدود المعاملات المشتركة وهذا الطرح القابل للتراجع، مع قياس مسار الدفع بالكامل. هل لديك سؤال حول هذا؟ ضعه في التعليقات. وهذا هو الفرق لهذا اليوم.

2:54 أنا نيكو من Axrisi. ادمج بمسؤولية.

المصادر

  1. We replaced Redis with MySQL for inventory reservations—and it scaledShopify Engineering — Emilie Noel
  2. Simplified reservation SQL embedded in Shopify's articleShopify Engineering / CourtneySymons on GitHub Gist
  3. MySQL 8.0 — Locking ReadsOracle / MySQL Reference Manual
  4. MySQL 8.0 — Transaction Isolation LevelsOracle / MySQL Reference Manual
  5. What Is Shopify and How Does It Work?Shopify
  6. Redis quick startsRedis documentation
  7. What is MySQL?Oracle / MySQL Reference Manual

فيديوهات ذات صلة