تتطلب جميع منتجات OpenAI وصولاً سريعاً وموثوقاً إلى البيانات، وهو ما توفره منصة التخزين لدينا، Habitat. ويجب أن تستجيب خلال أجزاء من الثانية لأكثر من 1 مليار مستخدم عبر 40 منطقة جغرافية. واجهت بنيتنا التحتية تحدياً استثنائياً: دعم النمو المتفجر وحالات الاستخدام الجديدة مع مواصلة تحسين الموثوقية والأداء وسرعة تطوير المنتجات. وقد تطلب حل ذلك التحدي إعادة التفكير في كيفية تصميم منصة التخزين الفوري لدينا وتشغيلها. قيّمنا المفاضلات باستمرار، باتباع النمط التالي: أن نصبح أولاً موثوقين بما يكفي لحركة المرور الحرجة للمنتجات، ثم سريعين بما يكفي للمستخدمين حول العالم، وأخيراً أن نعمل بمهارة على نطاق واسع جداً.
يشرح هذا العمل المكوّن من جزأين كيف طوّرنا Habitat من مكتبة عميل وبسيطة وقاعدة بيانات إلى منصة تخزين موزّعة عالميًا تخدم أكثر من 500 بيتابايت من البيانات. الجزء الأول ركزت على تطور Habitat من عميل بلغة بايثون إلى خدمة. كما تناولت التقنيات التي مكّنتنا من دفع خدمة قائمة على بايثون إلى ما هو أبعد بكثير مما قد يعتبره الكثيرون عمليًا.
في هذا المنشور، الجزء الثاني، نستعرض كيف قمنا بتوسيع نطاق مكوّن التخزين الأساسي: Azure Cosmos DB. ومن خلال شراكة عمل وثيقة مع فريق Azure، توصلنا إلى نهج قابل للتطبيق لتعدد المستأجرين يقوم على حاويات مُدارة بشكل مشترك، بأداء قراءة ممتاز على نطاق عالمي هائل.
الشكل 01 · ما هو Habitat؟
منصة تخزين سحابية (أونلاين)
Habitat هي منصة التخزين السحابية التي بنيناها لتمكّن منتجات OpenAI من الوصول السريع والموثوق إلى المعلومات المطلوبة.
- طلب
- استجابة
- تغييرات (CDC)
العملاء
منصة تخزين سحابية
موارد التخزين
- ChatGPT
- API
- Codex
- الخدمات الداخلية
- والمزيد
Habitat
- تخزين مؤقتذاكير تخزين مؤقت
- سياسات ACLمصادقة وتخويل
- التوزيع وإقامة البياناتإقامة البيانات
- التشفيرأمن البيانات
- العزلةتعدد المستأجرين
- تحديد المعدلتشكيل الطلبات
- التوجيهالبحث في المخططات · إقامة البيانات
- Azure Cosmos DBتخزين سحابي
- Nanobaseتخزين سحابي
- ValkeyCaches
- تخزين الكائنات الثنائية (Blob)موارد التخزين
- 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 هي إمكانية أن تُسقط العديد من الطلبات القادمة من منظمة شديدة النشاط أو مفتاح ساخن جدًا—أي مستأجر يولّد حملًا غير متناسب—قاعدة البيانات بأكملها. وقد بُذل جهد جماعي كبير لتخزين تلك المفاتيح مؤقتًا وبناء آليات إيجار في حالات فقدان الذاكرة المؤقتة بحيث لا يطغى الحمل الناتج عن فقدان الذاكرة المؤقتة على قاعدة البيانات الأساسية.
الشكل 02a · حدود مفاتيح الأقسام المنطقية
عملاء مختلفون، نفس مفتاح القسم
الجيران الصاخبون
بينما تنطبق حدود حجم البيانات والإنتاجية الموثقة على مفاتيح الأقسام المنطقية، فإن القسم الفعلي هو في الواقع المكان الذي تُفرض فيه الحدود. ومن الناحية العملية، هذا يعني أن الأقسام المنطقية غير قادرة على بلوغ 10,000 RU/s. بل إنها تتشارك حدود القسم الفعلي مع كل مفتاح قسم منطقي آخر موضوع في ذلك القسم الفعلي.
سمح هذا للجيران الصاخبين بالتأثير على العديد من مفاتيح الأقسام المنطقية غير ذات الصلة، حيث تعطلت الأحمال العاملة على بيانات لميزات منتجات متخصصة تدفقات تسجيل الدخول والتسجيل الأساسية.
الشكل 02b · الجيران الصاخبون
مستخدمون مختلفون، نفس القسم الفعلي
الأقسام الضعيفة
حد الإنتاجية لقسم فعلي معين متغير أيضًا، ويعتمد على إجمالي الإنتاجية المخصصة لحاوية Azure Cosmos DB. وتُوزَّع الإنتاجية المخصصة للحاوية بشكل شبه متساوٍ عبر الأقسام الفعلية لتلك الحاوية.
مع نمو حجم البيانات، تنقسم الأقسام الفعلية، مما يزيد عدد الأقسام الإجمالي بينما يبقى إجمالي الإنتاجية المخصصة دون تغيير. والنتيجة أن حد الإنتاجية الفعلي لكل قسم يتقلص مع نمو حجم البيانات.
بالنسبة إلى حالات الاستخدام لدينا الأكثر اعتمادًا على التخزين والتي تشبه الكائنات الثنائية كبيرة الحجم (blobs)، يخلق هذا نمط فشل حيث يؤدي نمو التخزين وحده إلى تقليل سعة الإنتاجية لأحمال العمل النشطة حتى مع بقاء معدلات الطلبات والاستخدام مستقرة.
الشكل 02C · الأقسام الضعيفة
الحد يقع تحت مستوى الطلب
ينقسم القسم عندما يصل إلى حد التخزين الخاص به. يتلقى كل قسم فرعي نصف سعة النقل.
قبل التقسيم: سعة 10K RU/s
بعد التقسيم: سعة 5K RU/s × 2 أقسام
المرحلة الثانية: محاولة عزل أعباء العمل والاستئجار الأحادي
تساعد الحاويات المنفصلة جزئيًا في حل هذه الحدود المتعلقة بمفاتيح الأقسام والجيران المزعجين. باستخدام حاويات منفصلة، يمكن تخصيص أقسام فيزيائية مستقلة لكل منها، وبالتالي فإن أعباء العمل المتغيرة على تلك الحاوية نفسها فقط هي التي قد تشكل جيرانًا مزعجين أو تتداخل في فضاء مفاتيح الأقسام. على الجانب السلبي، هناك عبء غير صفري في توفير حاويات جديدة—فكل حاوية تتطلب تخطيطًا فرديًا للسعة—لذلك نريد إنشاء حاويات فقط عند حدود الخدمة أو حالة الاستخدام التي يكون لها معنى.
بدأنا في استخدام حاويات Azure Cosmos DB منفصلة لأهم حالات الاستخدام الجديدة التي تتطلب عزلًا قويًا. ومع الجمع بين ذلك ونص برمجي لإدارة الأقسام الضعيفة عن طريق مزامنة إجمالي النقل المخصص لكل حاوية مع عدد أقسامها الفيزيائية، تجنبنا في معظمها جميع المشكلات التي كنا نواجهها.
ومع ذلك، بما أننا بدأنا بحاوية افتراضية، فإن العديد من حالات الاستخدام الحرجة القديمة كانت محاصرة هناك للأسف دون ترجيح بيانات. ولحماية الخدمات الحرجة التي لا تزال تعتمد على البيانات في الحاوية الافتراضية المشتركة، كنا ننصح الفرق غالبًا بإنشاء حاويات منفصلة للخدمات الجديدة أو ميزات المنتج الرئيسية. ومع توسعنا، زاد الضغط على الحاوية الافتراضية وزادت أيضًا حوادث الإنتاج. بدأنا في توفير حاويات لأي خدمة جديدة أو ميزة منتج كبيرة فقط لحماية الحاوية الافتراضية من مزيد من الحمل.
هذا أنقذنا من العديد من الانقطاعات على مستوى الموقع بالكامل، مما حدّ من نطاق التأثير إلى انقطاعات تدهور الميزات أو الخدمات. ومع ذلك،Catch لحق بنا في النهاية عبء توفير حاويات جديدة:
انعدام النمو الإجمالي المستقر
في الحاوية الافتراضية المشتركة القديمة، من غير المرجح أن تؤثر أي حالة استخدام جديدة تنتقل من 0 QPS إلى 1 مليون QPS بشكل كبير على إجمالي الاستخدام الكلي. أما في حاوية معزولة، فقد تمثل حالة استخدام جديدة تنتقل من 0 إلى 1 مليون QPS حملاً يزيد بمقدار 1,000 مرة عن خط الأساس المنسوب إلى الاستخدام الداخلي للتجربة الذاتية فقط.
مع الحاويات المخصصة، احتاجت الفرق الآن إلى تذكر توفير الحاويات مسبقًا بمستوى النقل المتوقع لإطلاقاتها. وكانت فرق المنتجات غالبًا تُطلق ميزاتها إلى الإنتاج وتنسى التوسع المسبق، وكنّا نجلس في غرف 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 بالفعل وضع بدون خوادم كان سيحل مشكلة الأقسام الضعيفة لدينا في الوضع المخصص. ومع ذلك، كان هناك عيب كبير: فهو كان يتوسع بناءً على استخدام التخزين فقط ويحد من استخدام RU إلى 5K RU/s لكل قسم فيزيائي. هذا كان سيحل مشكلة الأقسام الضعيفة لدينا، لكنه كان سيمنعنا من التوسع في حالات الاستخدام كثيفة RU.
وضع جديد محسّن بدون خوادم بناها لنا فريق Azure Cosmos DB سمح لكل قسم فيزيائي بالتوسع حتى 10K RU/s وأدخل تقسيمات قائمة على استخدام RU بالإضافة إلى التقسيمات القائمة على استخدام التخزين، مما أتاح لنا التوقف عن مراقبة الحاويات وتوسيعها يدويًا.
مع هذه التغييرات، تمكنا من العودة إلى استخدام حاوية مشتركة واحدة، مما بسّط بشكل كبير الحاجة إلى أي تخطيط مسبق أو مستمر للسعة من فرق المنتجات مع الحفاظ على العزل بين أحمال العمل. لم نواجه أي حوادث توفير أو جيران مزعجين في الأشهر منذ ذلك الحين، على الرغم من تسارع تطوير المنتجات.
موثوقية أفضل كخدمات مُدارة مشتركة
عندما تنمو الشركات إلى حجم OpenAI، تصبح الخدمات المُدارة أقل "إدارة". تصبح العديد من أحمال العمل حالات شاذة في بنية موفر الخدمات السحابية. ومع صعود OpenAI ليصبح أحد أكبر مستخدمي Azure Cosmos DB، تطلّب تشغيله بنجاح نموذجًا مختلفًا: اختبارات مشتركة، ولوحات معلومات مشتركة، وقنوات هندسية مباشرة، وملكية مشتركة لأنماط الفشل التي لا تظهر إلا على نطاقنا. اليوم، أكبر حساب لدينا في Azure Cosmos DB يخزن 10s من البتابايت من البيانات ويخدم أكثر من 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 عالميًا، أصبح زمن الاستجابة القيد التالي للمستخدمين وفرق المنتجات.
غالبًا ما كانت سعة الحوسبة والتخزين تقعان في مناطق مختلفة، مما جعل الطلبات عبر المناطق أمرًا لا مفر منه.
الشكل 04 · تحسين الأداء على نطاق عالمي
حركة المرور العالمية
غالبًا ما كانت سعة الحوسبة والتخزين تقعان في مناطق مختلفة، مما جعل الطلبات عبر المناطق أمرًا لا مفر منه.
المواقع الجغرافية للحوسبة والتخزين هي لأغراض توضيحية فقط.
كان زمن الاستجابة يتفاوت بشكل كبير اعتمادًا على مكان تخزين البيانات ومكان تقديم الطلب. ولجعل طلبات Habitat عالية الأداء، اعتمد مطورو المنتجات على تخزين مؤقت إضافي من جانب العميل، وتجميع الطلبات، وتقليل عمليات القراءة والكتابة في قاعدة البيانات، ونقل العمل خارج المسار الحرج كلما أمكن. وبينما أدى ذلك إلى بعض تصميمات المنتجات المثيرة التي كانت أكثر مرونة تجاه مشكلات قواعد البيانات، فقد جعل المنتجات أكثر تعقيدًا وأبطأ تكرار المنتجات: وهو إخفاق في تحقيق هدف Habitat المتمثل في تشجيع التطوير السريع للمنتجات وعدم الحاجة إلى فهم قاعدة البيانات.
لقد كان هذا محورًا كبيرًا لنا في 2026، وقد طورنا استراتيجية متعددة الطبقات لتحسين أداء القراءة، التي تمثل أكثر من 90% من طلبات Habitat:
تخزين البيانات قرب المستخدمين عندما تسمح السعة
لدينا عدد من حسابات Azure Cosmos DB في مناطق Azure مختلفة حول العالم للمستخدمين ذوي متطلبات إقامة البيانات. وحتى للمستخدمين دون متطلبات صارمة لإقامة البيانات، فإن وضع البيانات بالقرب من المستخدمين يحسّن تجربتهم أيضًا من خلال زمن استجابة أقل.
من الناحية العملية، لا يمكننا تحقيق هذا على نطاق واسع خارج حالات استخدام إقامة البيانات لأن التوزيع مقيّد بسعة السحابة الفعلية. ونظرًا لحجم مجموعات البيانات لدينا، لا تستطيع العديد من المناطق استيعاب حجم التخزين الضخم المطلوب لنصيبها التناسبي من حركة مرور المستخدمين.
في المناطق ذات السعة المحدودة لمراكز البيانات أو الطاقة أو التبريد، نواجه أحيانًا مفاضلة مباشرة: حجز السعة للتخزين المُساكن للحصول على زمن استجابة أقل لـ Habitat، أو استخدام تلك السعة لحوسبة إضافية للخدمة وتوجيه طلبات التخزين إلى مسافة أبعد.
نتيجة لذلك، غالبًا ما تكون قرارات التوزيع مفاضلة منتجية بين: أ) تحسين زمن الاستجابة لمنتجات وفئات مستخدمين مختلفة، وب) سعة التخزين والحوسبة الخام.
التكرار الواسع لمجموعات البيانات الأصغر فقط والأكثر حساسية لزمن الاستجابة
بالنسبة لأحمال العمل الأكثر حساسية لزمن الاستجابة، مثل بيانات المصادقة الوصفية المطلوبة في كل طلب، نقلل زمن الذهاب والإياب (RTT) بين الحوسبة وHabitat باستخدام حسابات Azure Cosmos DB عالية التكرار مع العديد من المناطق الثانوية. تتكرر بعض الحسابات إلى جميع مناطق Azure الـ 40 التي نخدم فيها حركة المرور؛ بينما تتكرر أخرى إلى منطقة واحدة على الأقل في كل قارة.
اضطررنا إلى بناء طبقة شفافة لنقل البيانات والتوجيه داخل Habitat في وقت أبكر مما كنا نرغب حتى نتمكن من نقل مجموعات البيانات بين حسابات ذات طوبولوجيات تكرار مختلفة.
غير أن هذا النهج يظل في نهاية المطاف مقيّدًا بالسعة، وبالتالي محدودًا ببضع مجموعات بيانات مختارة يدويًا.
الاعتماد على التخزين المؤقت المتكامل لكل شيء آخر
أحمال عمل Habitat ثقيلة القراءة في الغالب، مع قيام التطبيقات باستمرار بجلب الإعدادات والحالات وخصائص أخرى؛ وترتبط كمية غير متناسبة من حركة المرور بمجموعة عمل صغيرة نسبيًا من الأنواع ذات الوصول المتكرر. هذا يجعل النظام مناسبًا بشكل خاص للتخزين المؤقت الموزع. وبينما يحسّن التخزين المؤقت الأداء في البنية التحتية أحادية المنطقة، تتراكم التحسينات عند العمل عبر المناطق، حيث يمكن استخدامه لإخفاء زمن الاستجابة عبر المناطق.
لقد دمجنا طبقة تخزين مؤقت موزعة من نوع lookaside في Habitat. تخزن هذه الطبقة نسخة من الكائنات والحواف التي تم الوصول إليها مؤخرًا في خوادم Valkey موضوعة في بنيتنا التحتية قريبًا من حيث تُعالج طلبات المستخدمين. عادةً، تستخدم هذه الأنواع من المخازن المؤقتة TTL يقايض بين معدل الإصابة وقدم البيانات. فقيم TTL القصيرة تقلل القدم لكنها تخفف التأثير الإيجابي للتخزين المؤقت، لأن العناصر تنتهي صلاحيتها من المخزن بسرعة ويجب جلبها بشكل متكرر أكثر. أما قيم TTL الأطول فتحسّن معدلات الإصابة، لكنها تقدم بيانات قديمة لفترات ممتدة، مما يؤدي إلى تجارب مستخدم سيئة وسلوك منتجات غير متوقع.
نهج آخر هو تنفيذ عمليات إبطال صريحة عند قيام التطبيق بعمليات كتابة على نفس البيانات الأساسية. يحسّن هذا بشكل كبير حداثة البيانات المخزنة مؤقتًا، لكن قد يكون من الصعب تنفيذه بشكل صحيح. ويظل أيضًا عرضة لعدد من الحالات الحدية، مثل الفشل الجزئي، الذي يترك المخزن المؤقت قديمًا. وتضاعف عمليات النشر متعددة المناطق هذه المشكلات، مع شبكات أقل موثوقية عبر المناطق، وتسابق المخزن المؤقت مع تكرار التخزين الأساسي. والمزج بين هذا وقيم TTL يحدد أقصى قدم ممكنة، لكنه لا يزال يعاني من نفس مفاضلة TTL المذكورة أعلاه.
لقد اتخذنا نهجًا أكثر تقدمًا للإبطال، سيرًا على خطى أنظمة مثل TAO من Meta. يعتمد المخزن المؤقت المتكامل في Habitat على التقاط تغيّر البيانات (CDC) عبر تغذية التغييرات في Azure Cosmos DB لنشر الإبطالات عالميًا خلال ثوانٍ، محققًا معدلات إصابة عالية مع إبقاء قدم البيانات منخفضة. تستهلك خدمة في بنيتنا التحتية هذه التغذية وتنفذ عمليات الإبطال على المخازن المؤقتة المحلية عند تحديث البيانات الأساسية. يتسبب ذلك في فقد (miss) في المرة التالية التي تُقرأ فيها البيانات، ويُملأ المخزن المؤقت بأحدث نسخة من البيانات.
تقليل عبء الوكيل باستخدام Rust
كما قللنا بشكل كبير من زمن الاستجابة بإزالة العبء في خدمة Habitat نفسها من خلال إعادة كتابة الشيفرة بلغة Rust، وهي أكثر أداءً من Python الأصلية.
وقد أدّت هذه التغييرات مجتمعةً إلى خفض زمن القراءة p50 العالمي الإجمالي لدينا من نحو 120 مللي ثانية إلى نحو 10 مللي ثانية، أي بتحسين بمقدار 12 ضعفاً منذ أن بدأنا التركيز على الأداء في وقت سابق من هذا العام.
الشكل 05 · تحسين الأداء على نطاق عالمي
زمن الاستجابة p50 للقراءات
ثلاثة تغييرات رئيسية في التصميم حسّنت زمن استجابة القراءة
من نحو 120 مللي ثانية ← إلى نحو 10 مللي ثانية
تحسين بمقدار 12 ضعفاً
- نسخ البيانات الحرجة إلى مناطق جغرافية قريبة
- إطلاق التخزين المؤقت داخل المنطقة
- إطلاق إعادة الكتابة بلغة rust
وبينما أدّى التخزين المؤقت إلى خفض كبير في زمن الاستجابة الوسيط، لا تزال الطلبات الأبطأ تتطلب جلب بيانات غير مخزّنة مؤقتاً من وحدة التخزين الأساسية، وغالباً عبر مناطق بعيدة. ومع توفّر المزيد من السعة وتحسين كفاءة التخزين، نخطط لمعالجة تحدٍّ أكثر جوهرية: وضع البيانات منذ البداية أقرب إلى المكان الذي سيتم الوصول إليها منه.
توسيع نطاق Change Data Capture
يُعدّ نظام CDC الموثوق والقابل للتوسع—أي نقل تغييرات قاعدة البيانات إلى الأنظمة اللاحقة—مكوّناً أساسياً في أكثر من استراتيجية التخزين المؤقت لـ Habitat وحدها. فملايين التغييرات الملتقطة في الثانية، عبر آلاف الحاويات وملايين أقسام الحاويات، تتدفق عبر أكثر من مئة موضوع Kafka لتشغيل أيضاً فهارس ثانوية متسقة في نهاية المطاف، وخطوط أنابيب نقل البيانات، والتحليلات غير المتصلة، وميزات منتجات أخرى في الوقت الفعلي. ومع نمو بنيتنا التحتية الداعمة عالمياً، أصبح الاستماع إلى تغييرات الصفوف أمراً متزايد التعقيد. فإذا أراد أحد العملاء تسجيل دالة رد اتصال لتُنفَّذ كلما تغيّرت صفوف من نوعه، فعليه، من بين أمور أخرى، أن يحدد أولاً أيّ حسابات Cosmos والحاويات تحتوي على بياناته، وأيّ نشر لخدمة CDC يعمل في المناطق المعنية يستمع إلى تلك الحاويات، وأن يوسّع نطاق أسطول عمال خدمة CDC وKafka ومستهلكه بشكل صحيح. تهدف منصتنا CDC إلى تجريد كل هذا عن مطوري المنتجات وتوفير واجهة بسيطة بدلاً منه، يسجّل فيها العملاء دالة يرغبون في استدعائها على صفوفهم المتغيّرة ونحن نتولى جميع أعمال التوصيل والتوسع.
تضمن طبقة تحكم داخلية بشكل مستمر التقاط جميع الحاويات المطلوبة، وتختار مناطق Cosmos التي تُقرأ منها، وتوزّع العمل بكفاءة بين آلاف العمال عبر مناطق جغرافية متعددة. ويحمي استخدام مناطق النسخ المتماثلة وقراءات التغذية ذات الأولوية الأدنى حركة مرور Habitat الحساسة لزمن الاستجابة من أحمال الالتقاط الخلفية. وتحدث أعطال العمال، ومشاكل الحاويات، وأخطاء مخزن التأجير، والإعدادات غير الصالحة، وإخفاقات الوجهات باستمرار عبر أسطول بهذا الحجم. وقد عزّزنا دورة حياة عامل CDC ومعالجة التأجير، وعزلنا الأعطال بين التدفقات، وبنينا ضمانات لتغييرات الإعدادات ونشرها. ونستخدم قوائم الرسائل الميتة لمنع حجب رأس الطابور الناجم عن إخفاقات تسليم دائمة. ونتحمّل الانقطاعات الإقليمية عبر تحويل القرّاء إلى مناطق Cosmos بديلة. وعند نطاقنا، اضطررنا حتى إلى إجراء تغييرات على CDC SDK الخاص بـ Azure لجعل تنفيذ نقاط التحقق فيه أكثر كفاءة من خلال تجميع نقاط التحقق في الذاكرة ومسحها بشكل دوري فقط.
وبينما يُعدّ الاستخدام الداخلي لـ Azure Cosmos DB في Habitat معقداً، فإن قيمته المقترحة كانت دائماً هي تجريد تفاصيل البنية التحتية عن مطوري المنتجات لتحسين سرعة تطوير المنتجات، ومنصتنا CDC ليست استثناءً.
نظرة إلى المستقبل
تمكّن فريق صغير من دعم منصة تخزين سريعة النمو من خلال إبقاء واجهة تخزين API محدودة عن قصد، والاستمرار في توسيع نطاق خدمة Python، ومنح الأولوية لأكثر التحديات الهندسية إلحاحاً. ركّزنا أولاً على الموثوقية لحركة مرور المنتجات الحرجة، ثم على أداء القراءة للمستخدمين العالميين، وأخيراً على الكفاءة التشغيلية على نطاق واسع. وقد مكّن هذا النهج من النمو السريع وحالات الاستخدام الجديدة مع تحسين الموثوقية والأداء وسرعة تطوير المنتجات.
ومن أجل توسيع نطاق Habitat وتخزين المحادثات لمليار مستخدم قادمين، نحتاج إلى معالجة صعوبة نسخ بياناتنا عبر بنيتنا التحتية على نطاق أكبر بكثير. وللاستباق بذلك، كنّا نبني نظام تخزين داخلياً مخصصاً عبر الإنترنت بسعة تصل إلى الإكسابايت، محسّناً لأنواع بيانات Habitat الضخمة. يجمع هذا النظام قيد التطوير بين نواة RocksDB Cloud من Rockset والنسخ المتماثل القائم على Raft. وهو يطبّق نموذج المستندات ذاته المستخدم في Azure Cosmos DB، لكنه يستخدم تخزيناً مفككاً ونسخاً متماثلاً فيزيائياً لتقليل كمية سعة الفلاش المطلوبة، مقابل انخفاض في ذروة qps.
إذا كنت مهتماً بالعمل على هذه الأنواع من مشاريع البنية التحتية للبيانات على نطاق رائد, ألقِ نظرة على وظائفنا المفتوحة.