OpenAI Sitemapتاريخ نشر المصدر

توسيع نطاق التخزين السحابي بسرعة لخدمة أكثر من 1 مليار مستخدم لـ ChatGPT (الجزء الثاني)

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

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

تشرح هذه السلسلة المكونة من جزأين كيف طوّرنا Habitat من مكتبة عملاء بسيطة وقاعدة بيانات إلى منصة تخزين موزعة عالمياً تخدم أكثر من 500 بيتابايت من البيانات. ركز الجزء الأول على تطور Habitat من عميل بلغة Python إلى خدمة. كما تناول التقنيات التي سمحت لنا بدفع خدمة قائمة على Python إلى ما هو أبعد بكثير مما قد يعتبره الكثيرون عملياً.

في هذا المنشور، الجزء الثاني، نستعرض كيف قمنا بتوسيع نطاق مكوّن التخزين الأساسي: Azure Cosmos DB. ومن خلال شراكة عمل وثيقة مع فريق Azure، توصلنا إلى نهج قابل للتطبيق لتعدد الاستئجار يتمثل في الحاويات المُدارة بشكل مشترك، مع أداء قراءة ممتاز على نطاق عالمي ضخم.

الشكل 01 · ما هو Habitat؟

منصة التخزين السحابي

Habitat هي منصة التخزين السحابي التي بنيناها لتمكين منتجات OpenAI من الوصول إلى المعلومات المطلوبة بسرعة وموثوقية.

  • الطلب
  • الاستجابة
  • التغييرات (CDC)

العملاء

منصة التخزين السحابي

موارد التخزين

  • ChatGPT
  • API
  • Codex
  • الخدمات الداخلية
  • والمزيد

Habitat

  • التخزين المؤقت ذاكرات التخزين المؤقت
  • سياسات ACL التخويل
  • التوزيع وإقامة البيانات إقامة البيانات
  • التشفير أمن البيانات
  • العزل تعدد الاستئجار
  • تحديد المعدل تشكيل الطلبات
  • التوجيه البحث في المخطط · إقامة البيانات
  • Azure Cosmos DB التخزين السحابي
  • Nanobase التخزين السحابي
  • ValkeyCaches
  • تخزين Blob موارد التخزين
خدمات CDCتغيير التقاط البيانات
  • Databricks
  • Rockset
  • Kafka
  • والمزيد

جعل تعدد المستأجرين موثوقًا وقابلًا للتوسع

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

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

في Habitat، كان علينا الموازنة بين كل هذه المقايضات لتصميم نظام تخزين موثوق وفعال وقابل للتوسع. اليوم، Habitat هو طبقة قاعدة بيانات متعددة المستأجرين للعديد من منتجات OpenAI، لكننا مررنا برحلة دائرية من استخدام حاوية Azure Cosmos DB واحدة متعددة المستأجرين إلى توفير حاويات خلفية أحادية المستأجر ثم العودة إلى حاوية متعددة المستأجرين كإعداد افتراضي. ما زلنا في بداياتنا جدًا في قصة تعدد المستأجرين على Habitat: ندعم مجموعة كبيرة من حالات الاستخدام، لكننا تمكنا من تأجيل الاستثمار في هذا المجال بالاستفادة من العناصر الأساسية المدمجة في Azure Cosmos DB كلما أمكن ذلك.

ملخص مبسط عن حاويات Azure Cosmos DB

قبل استعراض رحلتنا مع Azure Cosmos DB، إليك بعض السياق الأساسي:

  • يحدد حساب Azure Cosmos DB مجموعة من الحاويات وسياسة نسخ متماثل

  • تُجهَّز كل حاوية بمقدار معين من الإنتاجية بوحدات الطلب في الثانية (RU/s)

  • تُخزَّن البيانات داخل كل حاوية بالطريقة المعتادة للتقسيم الشظوي حسب مفتاح قسم منطقي محدد، مع حدود موثقة على التخزين والإنتاجية لكل مفتاح قسم منطقي

  • يتولى Azure Cosmos DB تقسيم مفاتيح الأقسام المنطقية عبر عدد أقل من الأقسام الفيزيائية الخلفية، وفصلها إلى أقسام فيزيائية متعددة عندما يتجاوز التخزين حدًا معينًا أو عندما تحتاج الحاوية إلى أقسام فيزيائية أكثر للحفاظ على الإنتاجية المجهزة

المرحلة الأولى: الاعتماد على العناصر الأساسية في Azure Cosmos DB

في البداية، سمحنا بمرور أي حمل من العملاء، معتمدين على الحد المعلن البالغ 10K RU/s لكل مفتاح قسم منطقي لتوفير ضغط عكسي. وعند البداية، استخدمنا أيضًا حاوية Azure Cosmos DB افتراضية واحدة فقط في كل حساب. نجح هذا بشكل كافٍ، لكنه أثبت إشكاليته لعدة أسباب:

حدود مفاتيح الأقسام المنطقية

نظرًا لخيارات API المبكرة، عرضنا اختيار مفتاح القسم المنطقي مباشرة على العملاء. ونتيجة لذلك، نواجه تصادمات متكررة على مفاتيح الأقسام الشائعة الاستخدام، مثل user_id أو workspace_id، عبر حالات استخدام منتجات مختلفة. ولأن حالات الاستخدام هذه كانت تتشارك حدود Azure Cosmos DB على نفس مفاتيح الأقسام المنطقية، فقد قيّد هذا التصميم الإنتاجية الإجمالية لمستخدم معين.

أحد المشكلات الشائعة التي واجهناها في توسيع Postgres قبل انتقالنا إلى Habitat وAzure Cosmos DB كان احتمال أن تتسبب طلبات كثيرة من مؤسسة شديدة النشاط أو مفتاح ساخن—أي مستأجر يولد حملاً غير متناسب—في تعطيل قاعدة البيانات بأكملها. وتم بذل جهد جماعي كبير لتخزين تلك المفاتيح مؤقتًا وبناء عقود إيجار (leases) في حالات فقد التخزين المؤقت بحيث لا يطغى الحمل الناتج عن فقد التخزين المؤقت على قاعدة البيانات الأساسية.

الشكل 02a · حدود مفاتيح الأقسام المنطقية

عملاء مختلفون، نفس مفتاح القسم

الجيران الصاخبون

بينما تنطبق حدود حجم البيانات والإنتاجية الموثقة على مفاتيح الأقسام المنطقية، فإن الحد يُفرض فعليًا على مستوى القسم الفيزيائي. وهذا يعني عمليًا أن الأقسام المنطقية غير قادرة على الوصول إلى 10,000 RU/s. وبدلاً من ذلك، تتشارك حدود القسم الفيزيائي مع كل مفتاح قسم منطقي آخر مكانه على ذلك القسم الفيزيائي.

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

الشكل 02b · الجيران الصاخبون

مستخدمون مختلفون، نفس القسم الفيزيائي

الأقسام الضعيفة

حد الإنتاجية لقسم فيزيائي معين متغير أيضًا، ويتوقف على إجمالي الإنتاجية المخصصة لحاوية Azure Cosmos DB. حيث تُوزَّع الإنتاجية المجهزة للحاوية تقريبًا بالتساوي عبر الأقسام الفيزيائية لتلك الحاوية.

ومع نمو حجم البيانات، تنقسم الأقسام الفيزيائية، مما يزيد العدد الإجمالي للأقسام بينما يبقى إجمالي الإنتاجية المجهزة دون تغيير. والنتيجة أن حد الإنتاجية الفعلي لكل قسم يتقلص مع نمو حجم البيانات.

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

الشكل 02C · أقسام ضعيفة

الحد ينخفض دون مستوى الطلب

ينقسم القسم (Partition) عندما يصل إلى حد التخزين الخاص به. يتلقى كل قسم فرعي نصف سعة الإنتاجية.

قبل الانقسام: سعة 10K RU/s

بعد الانقسام: سعة 5K RU/s × 2 أقسام

المرحلة الثانية: محاولة عزل أحمال العمل والاستضافة الأحادية (single-tenancy)

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

بدأنا في استخدام حاويات Azure Cosmos DB منفصلة لأكثر حالات الاستخدام الجديدة أهمية والتي تتطلب عزلًا قويًا. وبالاقتران مع سكربت لإدارة الأقسام الضعيفة عن طريق مزامنة إجمالي الإنتاجية الموفرة لكل حاوية مع عدد أقسامها الفيزيائية، تجنبنا في الغالب جميع المشكلات التي كنا نواجهها.

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

أنقذنا هذا من العديد من الانقطاعات على مستوى الموقع بأكمله، مما حدّ من نطاق التأثير إلى انقطاعات تدهور في ميزة أو خدمة. ومع ذلك، لم تمضِ طويل حتى لحقت بنا تكلفة توفير حاويات جديدة:

غياب النمو الإجمالي المستقر

في حاوية الافتراضية المشتركة القديمة، كان من غير المرجح أن تؤثر أي حالة استخدام جديدة تنتقل من 0 QPS إلى 1 مليون QPS بشكل كبير على إجمالي الاستخدام الكلي. أما في حاوية معزولة، فقد تمثل حالة استخدام جديدة تنتقل من 0 إلى 1 مليون QPS حملاً يزيد بمقدار 1,000 مرة عن خط الأساس المنسوب إلى الاختبار الداخلي فقط (dogfooding).

مع الحاويات المخصصة، احتاجت الفرق الآن إلى تذكر توفير الحاويات مسبقًا بالمستوى المتوقع من الإنتاجية لإطلاقاتها. كانت فرق المنتج غالبًا ما تُطلق ميزاتها إلى بيئة الإنتاج وتنسى التوسع المسبق، وكنا نجلس في غرف SEV يوم الإطلاق ونحاول توسيع الحاويات في اللحظة الأخيرة.

هذه ميزة أساسية لمزج أحمال العمل في الأنظمة متعددة المستأجرين نفقد مع هذه الاستراتيجية للحاويات لصالح عزل أفضل.

الشكل 03 · غياب النمو الإجمالي المستقر

نفس حمل العمل، هامش مختلف

1K RU/s أثناء اختبار الحمل ← 1M RU/s عند الإطلاق

الحاوية المشتركة

سعة 100M RU/s · مستغلة بنسبة 80%

اختبار الحمل

1K20M=

0.005%

من الهامش

الإطلاق

1M20M=

5%

من الهامش

حاوية مخصصة جديدة

سعة 10K RU/s · لا أحمال عمل أخرى

اختبار الحمل

1K10K=

10%

من الهامش

الإطلاق

1M10K=

10,000%

من الهامش

تخطيط السعة

مع مرور الوقت، كان رصد استخدام الحاويات المخصصة يتطلب أيضًا معرفة وثيقة بالمنتج لمعرفة متى سيتحرك حجم الزيارات أو ينمو.

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

فشل هذا في التوسع تنظيميًا مع وجود تفاوت واسع في مدى العناية التي يوليها الفريق المالك لكل خدمة لتوفير Azure Cosmos DB الخاص بها.

المرحلة الثالثة: استخدام تعدد الاستئجار افتراضيًا مع إمكانية نقل البيانات

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

خنق المفاتيح الساخنة

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

جودة الخدمة (QoS)

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

الوضع بدون خادم

كان لدى Azure Cosmos DB بالفعل وضع بدون خادم كان سيعالج مشكلة الأقسام الضعيفة لدينا في الوضع الموفّر. لكن كان هناك عيب كبير: فهو كان يتوسع بناءً على استخدام التخزين فقط وكان يحد من استخدام RUs إلى 5K RU/s لكل قسم فيزيائي. هذا كان سيحل مشكلة الأقسام الضعيفة لدينا، لكنه كان سيمنعنا من التوسع في حالات الاستخدام كثيفة الاعتماد على RUs.

وضع بدون خادم جديد ومحسّن بناله فريق Azure Cosmos DB سمح لكل قسم فيزيائي بالتوسع حتى 10K RU/s وأدخل تقسيمات بناءً على استخدام RUs بالإضافة إلى التقسيمات القائمة على استخدام التخزين، مما أتاح لنا التوقف عن رصد الحاويات وتوسيعها يدويًا.

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

موثوقية أفضل كخدمات مُدارة بشكل مشترك

عندما تنمو الشركات إلى حجم OpenAI، تصبح الخدمات المُدارة أقل "إدارة". فالكثير من أعباء العمل تصبح شاذة في بنية مزوّد السحابة. وبما أن OpenAI أصبح أحد أكبر مستخدمي Azure Cosmos DB، فإن تشغيله بنجاح تطلّب نموذجًا مختلفًا: اختبارات مشتركة، ولوحات معلومات مشتركة، وقنوات هندسية مباشرة، وملكية مشتركة لأنماط الفشل التي لا تظهر إلا عند حجمنا. اليوم، يخزّن أكبر حساب Azure Cosmos DB لدينا 10ات من البايتابايتات من البيانات ويخدم أكثر من 20M QPS. وعلى حد علمنا، نحن الشركة الوحيدة التي نشرت Azure Cosmos DB بهذا الحجم.

في أواخر عام 2024، جعل انقطاع إقليمي من الواضح لماذا كان هذا التعاون ضروريًا. في ذلك الوقت، ضرب انقطاع التيار الكهربائي الإقليم الأساسي لـ Azure لأحد أكبر حسابات Azure Cosmos DB لدينا. وفي تمرين التحويل الفاشل الناتج، أدركنا أن أكبر حساباتنا ستستغرق عدة ساعات للتحويل إلى إقليم ثانوي، وهو أمر لم يختبره فريقنا ولا فريق Azure Cosmos DB عند حجمنا.

بعد حوالي شهر، أثناء إعادة تلك الحسابات إلى الإقليم الأصلي، أحدثنا انقطاعًا آخر خطيرًا. فقد أغرق هجوم اتصالات على الإقليم الأصلي بوابة Azure Cosmos DB في ذلك الإقليم. وسبب خصيص غير متوقع في كيفية تعامل عميل Azure Cosmos DB في وضع البوابة مع التحويلات الفاشلة جميع العملاء على إنشاء اتصالات فورًا وإرسال الطلبات إلى الإقليم الأصلي، رغم أن مجموعة فرعية فقط من الأقسام الفيزيائية كانت قد انتقلت عائدة إلى ذلك الإقليم.

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

اليوم، تراقب فرق هندسة Habitat وAzure معًا كل طبقة من Habitat من طبقات خدماتنا وصولاً إلى طبقات التخزين الفيزيائية في Azure Cosmos DB. نقوم بتشغيل واختبار التغييرات مقابل حساب Azure Cosmos DB بحجم الإنتاج لكنه غير إنتاجي. نختبر ونكرر على حزم تطوير البرمجيات SDK معًا ونحدد أفضل الممارسات لكيفية توسيع حسابات Azure Cosmos DB وتحديد أحجامها. لدينا وصول هندسي مباشر إلى بعضنا البعض عبر Teams بل وقد كشفنا طرقًا للاتصال المباشر ببعضنا دون المرور بمستويات الدعم.

تم تنفيذ قدر كبير من العمل المشترك خلال العام الماضي لتحسين قابلية التوسع في طبقة التحكم والبوابة في Azure Cosmos DB، بما في ذلك إضافة حماية من الأحمال والتخزين المؤقت لبيانات وصفية متنوعة لـ Azure Cosmos DB في بوابتهم لحماية قسم البيانات الوصفية في Azure Cosmos DB، وتقليل الضغط من أسطولنا من عمليات habitat-service المكتوبة بلغة Python عبر تجميع الاتصالات وإعادة استخدام الاتصالات بمستوى أعلى، وتجميع أعباء العمل في مكان واحد حيثما أمكن، وعزل أعباء العمل الحرجة عن أعباء العمل غير المتصلة عبر شبكات VPC مختلفة.

كان هذا المستوى من الهندسة المشتركة بالغ الأهمية لاستقرار Azure Cosmos DB لدينا خلال العام الماضي. أي نظام كبير أو حرج بما يكفي يستلزم هذا النوع من العمل الجماعي: تفكيك جدران الملكية والعمل عبر الحدود التنظيمية.

تحسين الأداء على نطاق عالمي

كما ذُكر في الجزء الأول، فإن فلسفتنا الجوهرية هي: اجعله يعمل، ثم اجعله سريعًا، ثم اجعله رخيصًا. الموثوقية أولًا، ثم الأداء، ثم الكفاءة. لقد أصبح Habitat بنية تحتية حرجة لـ OpenAI، لذا كان الأولوية الأولى هي جعله موثوقًا. وباستقرار النظام في عام 2025 وتوسع OpenAI عالميًا، أصبح زمن الاستجابة (latency) القيد التالي للمستخدمين وفرق المنتجات.

كانت سعة الحوسبة والتخزين تقع غالبًا في مناطق مختلفة، مما جعل الطلبات العابرة للمناطق أمرًا لا مفر منه.

الشكل 04 · تحسين الأداء على نطاق عالمي

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

كانت سعة الحوسبة والتخزين تقع غالبًا في مناطق مختلفة، مما جعل الطلبات العابرة للمناطق أمرًا لا مفر منه.

الحوسبةالتخزينمسارات توضيحية · الرحلات الأطول تستغرق وقتًا أطول

المواقع الجغرافية للحوسبة والتخزين لأغراض توضيحية فقط.

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

لقد كان هذا محور تركيز كبير لنا في عام 2026، وقد طورنا استراتيجية متعددة الطبقات لتحسين أداء القراءة، والتي تمثل أكثر من 90% من طلبات Habitat:

تخزين البيانات قرب المستخدمين عندما تسمح السعة

لدينا عدد من حسابات Azure Cosmos DB في مناطق Azure مختلفة حول العالم للمستخدمين الذين لديهم متطلبات إقامة البيانات (data residency). وحتى للمستخدمين الذين لا توجد لديهم متطلبات صارمة لإقامة البيانات، فإن وضع البيانات قرب المستخدمين يحسّن تجربتهم أيضًا من خلال زمن استجابة أقل.

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

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

ونتيجة لذلك، غالبًا ما تكون قرارات التوزيع مفاضلة منتجات بين: أ) تحسين زمن الاستجابة لمنتجات مختلفة وفئات فرعية من المستخدمين، و ب) سعة التخزين والحوسبة الخام.

التكرار الواسع لمجموعات البيانات الأصغر والأكثر حساسية لزمن الاستجابة فقط

بالنسبة لأعباء العمل الأكثر حرجية من حيث زمن الاستجابة، مثل بيانات المصادقة الوصفية (metadata) المطلوبة في كل طلب، نقلل زمن الذهاب والإياب (RTT) بين الحوسبة وHabitat باستخدام حسابات Azure Cosmos DB عالية التكرار مع العديد من المناطق الثانوية. بعض الحسابات تُكرر إلى جميع مناطق Azure الـ 40 التي نخدم فيها حركة المرور؛ وبعضها الآخر يُكرر إلى منطقة واحدة على الأقل في كل قارة.

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

غير أن هذا النهج يظل في نهاية المطاف محدودًا بالسعة، وبالتالي يقتصر على عدد قليل من مجموعات البيانات المختارة يدويًا.

الاعتماد على التخزين المؤقت المدمج لكل ما عدا ذلك

أعباء عمل Habitat قراءة الأغلبية بامتياز، حيث تجلب التطبيقات باستمرار الإعدادات والحالة وخصائص أخرى؛ ونسبة غير متناسبة من حركة المرور تعود إلى مجموعة عمل صغيرة نسبيًا من الأنواع شائعة الوصول. وهذا يجعل النظام ملائمًا بشكل خاص للتخزين المؤقت الموزع. وفي حين يحسّن التخزين المؤقت الأداء في البنية التحتية أحادية المنطقة، تتراكم التحسينات عند العمل عبر المناطق، حيث يمكن استخدامه "لإخفاء" زمن الاستجابة العابر للمناطق.

لقد دمجنا طبقة تخزين مؤقت موزعة من نوع lookaside داخل Habitat. فهي تخزن نسخة من الكائنات والحواف التي وصل إليها مؤخرًا في خوادم Valkey موضوعة في بنيتنا التحتية قريبًا من المكان الذي تُعالج فيه طلبات المستخدمين. عادةً ما تستخدم هذه الأنواع من الذاكرة المؤقتة مدة بقاء (TTL) توازن بين معدل الإصابة وحداثة البيانات. المدد القصيرة تقلل التقادم لكنها تُضعف الأثر الإيجابي للتخزين المؤقت، لأن العناصر تنتهي صلاحيتها من الذاكرة بسرعة ويجب جلبها بشكل متكرر. المدد الأطول تحسّن معدلات الإصابة، لكنها تقدم بيانات قديمة لفترات ممتدة، مما يؤدي إلى تجارب مستخدم سيئة وسلوك منتج غير متوقع.

وهناك نهج آخر يتمثل في تنفيذ عمليات إبطال صريحة عندما يقوم التطبيق بعمليات كتابة على نفس البيانات الأساسية. وهذا يحسّن بشكل كبير حداثة البيانات المخزنة مؤقتًا، لكنه قد يكون صعب الإتقان. ويظل أيضًا خاضعًا لعدد من الحالات الحدية، مثل الأعطال الجزئية التي تترك الذاكرة المؤقتة قديمة. وتؤدي النشرات متعددة المناطق إلى تفاقم هذه المشاكل، مع شبكات عابرة للمناطق أقل موثوقية، والذاكرة المؤقتة التي تتنافس مع تكرار التخزين الأساسي. ومكملةً ذلك بالمؤقتات الزمنية (TTLs) تُقيَّد أقصى درجة تقادم، لكنها لا تزال تعاني من نفس المفاضلة الأساسية للمؤقت الزمني المذكورة أعلاه.

لقد اتبعنا نهجًا أكثر تقدمًا في الإبطال، سيرًا على خطى أنظمة مثل TAO من Meta. يعتمد الذاكرة المؤقتة المدمجة في Habitat على التقاط تغييرات البيانات (CDC) عبر تغذية التغييرات (change feed) في Azure Cosmos DB لنشر الإبطالات عالميًا خلال ثوانٍ، محققةً معدلات إصابة عالية مع إبقاء التقادم منخفضًا. تستهلك خدمة في بنيتنا التحتية هذه التغذية وتنفذ الإبطالات على الذاكرة المؤقتة المحلية عند تحديث البيانات الأساسية. يتسبب ذلك في حدوث إصابة (miss) في المرة التالية التي تُقرأ فيها البيانات، ثم تُملأ الذاكرة المؤقتة بأحدث نسخة من البيانات.

تقليل عبء الوكيل باستخدام Rust

لقد خفضنا أيضًا زمن الاستجابة بشكل كبير بإزالة العبء الزائد في خدمة Habitat نفسها من خلال إعادة كتابة الشيفرة بلغة Rust، وهي أكثر كفاءة في الأداء من لغة Python الأصلية.

معًا، أدت هذه التغييرات إلى تخفيض قيمة read p50 العامة لدينا عالميًا من نحو 120 ms إلى نحو 10 ms، أي تحسّن بمقدار 12x منذ أن بدأنا التركيز على الأداء في وقت سابق من هذا العام.

الشكل 05 · تحسين الأداء على نطاق عالمي

زمن p50 لعمليات القراءة

ثلاثة تغييرات تصميمية رئيسية حسّنت زمن القراءة

نحو 120 ms → نحو 10 ms

تحسّن بمقدار 12x

  1. نسخ البيانات الحرجة إلى geos قريبة
  2. إطلاق التخزين المؤقت داخل المنطقة
  3. إطلاق إعادة الكتابة بـ rust

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

توسيع نطاق Change Data Capture

يُعدّ CDC الموثوق والقابل للتوسع—أي نشر تغييرات قاعدة البيانات إلى الأنظمة اللاحقة—مكوّنًا حاسمًا في أكثر من مجرد استراتيجية التخزين المؤقت في Habitat. ملايين التغييرات المُلتقطة في الثانية، عبر آلاف الحاويات وملايين أقسام الحاويات، تمر عبر أكثر من مئة موضوع Kafka لتشغيل أيضًا الفهارس الثانوية المتسقة في نهاية المطاف، وخطوط أنابيب نقل البيانات، والتحليلات غير المتصلة، وميزات منتجات أخرى في الوقت الفعلي. ومع نمو بنيتنا التحتية الداعمة عالميًا، أصبح الاستماع إلى تغييرات الصفوف أكثر تعقيدًا. إذا أراد أحد العملاء تسجيل callback يعمل كلما تغيّرت صفوف نوعه، فعليه، من بين أمور أخرى، أن يحدد أولًا حسابات Cosmos والحاويات التي تحتوي على بياناته، وأي نشر من نشرات خدمة CDC يعمل في المناطق المعنية ويستمع إلى تلك الحاويات، وأن يوسّع بشكل صحيح أسطول عمال خدمة CDC وKafka ومستهلكه. تهدف منصة CDC لدينا إلى إخفاء كل هذا عن مطوري المنتجات وتوفير واجهة بسيطة بدلًا منه، يسجّل فيها العملاء دالة يرغبون في استدعائها عند تغيّر صفوفهم، ونحن نتولى كل أعمال التوصيل والتوسيع.

تضمن مستوى تحكم داخلي باستمرار أن جميع الحاويات المطلوبة تُلتقط، ويختار مناطق Cosmos التي يقرأ منها، ويوزّع العمل بكفاءة بين آلاف العمال عبر مناطق جغرافية متعددة. ويحمي استخدام مناطق النسخ المتماثلة وقراءات feed ذات الأولوية الأدنى حركة مرور Habitat الحساسة لزمن الانتقال من أحمال الالتقاط في الخلفية. تحدث أعطال العمال، ومشكلات الحاويات، وأخطاء lease-store، والإعدادات غير الصالحة، وإخفاقات الوجهات باستمرار عبر أسطول بهذا الحجم. لقد عززنا دورة حياة عامل CDC ومعالجة leases، وعزلنا الأعطال بين التدفقات، وبنينا ضمانات لتغييرات الإعدادات والنشرات. نستخدم قوائم الرسائل الميتة (dead letter queues) لمنع حجب رأس الطبقة الناتج عن إخفاقات تسليم دائمة. ونتحمّل الانقطاعات الإقليمية عبر تحويل القرّاء إلى مناطق Cosmos بديلة. وعلى نطاقنا، اضطررنا حتى إلى إجراء تغييرات على Azure’s CDC SDK لجعل تنفيذ التحقق من النقاط (checkpointing) أكثر كفاءة عبر تجميع checkpoints في الذاكرة ومسحها دوريًا فقط.

وبينما كان استخدام Habitat الداخلي لـ Azure Cosmos DB معقدًا، ظلت قيمته المقترحة دائمًا هي إخفاء تفاصيل البنية التحتية عن مطوري المنتجات لتحسين سرعة تطوير المنتجات، ومنصة CDC لدينا ليست استثناءً.

النظرة إلى المستقبل

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

ومن أجل توسيع نطاق Habitat وتخزين المحادثات لمليار مستخدم قادم، نحتاج إلى معالجة صعوبة نسخ بياناتنا عبر بنيتنا التحتية على نطاق أكبر بكثير. وللاستباقية في ذلك، كنا نبني نظام تخزين داخليًا مخصصًا عبر الإنترنت بمقياس إكسابايت، محسّنًا لأنواع بيانات Habitat الضخمة. يجمع هذا النظام قيد التطوير بين نواة RocksDB Cloud من Rockset والنسخ المتماثل القائم على Raft. يطبّق نفس نموذج المستندات الخاص بـ Azure Cosmos DB، لكنه يستخدم تخزينًا منفصلًا (disaggregated) ونسخًا متماثلًا فيزيائيًا لتقليل كمية سعة الفلاش المطلوبة، مقابل qps ذروة أقل.

إذا كنت مهتمًا بالعمل على هذا النوع من جهود البنية التحتية للبيانات على مقياس رائد، ألقِ نظرة على وظائفنا المفتوحة⁠.

المصدر الأصلي

OpenAI Sitemap

ملاحظات المحتوى

النشر الأصلي والحقوق تعود إلى المصدر.

ترجمة آلية · يُرجى الرجوع إلى الأصل