Transcript
00:00:00كم قد يكلفك بايت واحد حقاً؟
00:00:02حسنًا، في نطاق عمل كلودفلير (Cloudflare)، فإن إهدار بايت واحد لكل مدخل
00:00:04يكلفهم أكثر من 250 جيجابايت من الذاكرة
00:00:06عبر أسطول خوادمهم بأكمله،
00:00:08ومؤخراً قاموا في الواقع بتقليص ذاكرة المدخل الواحد إلى النصف،
00:00:11مما أتاح توفير 100 تيرابايت من الذاكرة.
00:00:13في ظل هذا الوضع الاقتصادي، يعد هذا مبلغاً ضخماً من المال.
00:00:15لقد فعلوا ذلك في الواقع بخمسة تغييرات بسيطة للغاية
00:00:17على نظام التخزين المؤقت الخاص بهم،
00:00:18وجعلوا نظام أسماء النطاقات (DNS) أسرع في الوقت ذاته،
00:00:21لذا دعونا نتعمق ونرى كيف فعلوا ذلك.
00:00:27ربما تكون قد سمعت عن 1.1.1.1 من قبل.
00:00:30إنه خادم تحليل أسماء النطاقات العام الخاص بكلودفلير،
00:00:32وهو يعمل عن طريق أخذ النطاق الذي تريد الانتقال إليه،
00:00:34مثل betterstack.com،
00:00:35ومعرفة عنوان بروتوكول الإنترنت (IP) الحقيقي لهذا النطاق.
00:00:39أما الشيء الذي يقوم بهذا العمل بالفعل،
00:00:40فيُسمى (Big Pineapple)، ومكتوب بلغة رست (Rust)،
00:00:42وكما يمكنك أن تخمن على الأرجح، فإن هذا البرنامج نشط بشكل لا يُصدق،
00:00:43إنه برنامج مشغول بشكل لا يصدق،
00:00:46حيث يخزن أكثر من 250 مليار مدخل تخزين مؤقت لأسماء النطاقات في أي وقت.
00:00:50يضمن هذا أنه إذا أراد شخص ما زيارة betterstack.com
00:00:52بعد ثانٍ من قيام شخص آخر بذلك،
00:00:53فلن يضطر إلى اجتياز تسلسل أسماء النطاقات بأكمله مرة أخرى،
00:00:56بل يحتفظ بالإجابة في الذاكرة ويقدمها مباشرة.
00:00:59ولكن كما ذكرت في المقدمة،
00:01:01أن وجود 250 مليار مدخل في التخزين المؤقت يعني أن بايت واحد مهدر لكل مدخل
00:01:04يكلفهم نحو 250 جيجابايت من ذاكرة الوصول العشوائي (RAM)،
00:01:07ولهذا السبب كان لهذه التغييرات الخمسة تأثير كبير جداً.
00:01:10أولاً، لدينا تكلفة السعة.
00:01:12إليك الشكل الذي كان عليه مدخل التخزين المؤقت سابقاً.
00:01:14الطابع الزمني، وقت البقاء (TTL)، عدادات مرات الوصول،
00:01:16ثم مجموعة من المتجهات (Vectors).
00:01:17متجه لسجلات الإجابات،
00:01:18متجه لسجلات المصدر،
00:01:20متجه لسجلات إضافية،
00:01:21مجموعة من الأخطاء،
00:01:22والمزيد غير ذلك.
00:01:23بالنسبة لمن ليسوا على دراية بلغة رست،
00:01:25المتجه هو ببساطة نوع البيانات الأساسي للقوائم القابلة للتوسيع،
00:01:27وهو يتكون أيضاً من ثلاثة أشياء في الذاكرة.
00:01:29مؤشر (Pointer)، وطول، وسعة.
00:01:31وهي تمثل المساحة المحجوزة للنمو،
00:01:32بحيث لا يضطر إلى إعادة تخصيص الذاكرة في كل مرة تضيف فيها بيانات جديدة.
00:01:35وهو أمر مفيد للغاية إذا كان العنصر في حال نمو مستمر.
00:01:38ولكنهم نظروا إلى مداخل التخزين المؤقت الفعلية لأسماء النطاقات،
00:01:40وأدركوا أن كل شيء كان يُكتب في التخزين المؤقت
00:01:42ولا يُقرب أو يُعدل مرة أخرى.
00:01:44كان يتم قراءته فقط،
00:01:45لذلك لم تكن هذه المتجهات تنمو في الواقع.
00:01:47هذا يعني وجود مساحة مخصصة في الكومة (Heap) بلا داعٍ،
00:01:49ومهدرة هكذا.
00:01:50يوجد متجه بسعة تخزين لثمانية عناصر،
00:01:52ولكن مخزّن بداخله خمسة فقط،
00:01:53مما يترك ثلاثة أماكن غير مستخدمة،
00:01:55وحقل السعة نفسه هو من نوع (usize)،
00:01:57وهو ما يمثل ثمانية بايتات من الذاكرة،
00:01:58وهو أمر لا حاجة إليه بالنسبة لهم على الإطلاق.
00:02:00الآن، كان الحل لهذه المشكلة بسيطاً بشكل لا يصدق.
00:02:02ببساطة استبدل المتجه بصندوق (Box)،
00:02:04حيث إن حجم الصندوق يكون ثابتاً عند الحجم الذي تم إنشاؤه به،
00:02:07لذا فهو لا يحتاج إلى حقل سعة،
00:02:08كما أنه يخزن بدقة ما هو موجود هناك فقط.
00:02:10وهو لا يحتاج إلى تخصيص سعة إضافية للمستقبل.
00:02:13وأدركوا أيضاً أنه يمكنهم تطبيق نفس هذا التوفير تماماً
00:02:15على حقول النصوص أيضاً،
00:02:16حيث إنها في الأساس عبارة عن متجه من أنواع U8،
00:02:18بحيث يمكن للنص أن يكبر أو ينكمش،
00:02:20ولكن إذا لم تكن بحاجة إلى ذلك،
00:02:21يمكنك ببساطة استخدام مقطع نصي معبأ (Boxed string slice)،
00:02:23أي أن هذا النص لن يتغير.
00:02:26إجمالاً، في مدخل التخزين المؤقت الواحد،
00:02:27كان هناك ثمانية حقول من المتجهات والنصوص،
00:02:29لذا فإن استبدالها بصندوق أدى إلى توفير ثمانية بايتات لكل حقل،
00:02:31و64 بايت لكل مدخل،
00:02:33فضلاً عن التخلص من مساحة الكومة الزائدة
00:02:35التي يحجزها المتجه للنمو المستقبلي،
00:02:36مما يعني أن إجمالي التوفير المجتمع تجاوز 15 تيرابايت
00:02:39عند قياسه على 250 مليار مدخل في التخزين المؤقت.
00:02:42كل ذلك جاء نتيجة تغيير بسيط في نوع البيانات.
00:02:45أما بالنسبة للتغيير التالي،
00:02:46فقد نظروا في الواقع إلى بعض تلك القوائم،
00:02:48وتساءلوا ببساطة: هل نحن بحاجة إليها أصلاً؟
00:02:50يحتوي رد نظام أسماء النطاقات على ثلاثة مداخل،
00:02:52الإجابة، المصدر، والإضافي،
00:02:54وكما رأينا سابقاً،
00:02:55فقد تم تخزين هذه البيانات مؤقتاً عند ورودها
00:02:57في ثلاث قوائم منفصلة،
00:02:58وعلى الرغم من أننا أزلنا حقل السعة في التغيير الأول،
00:03:01فلا يزال كل متجه يتكون من مؤشر وطول،
00:03:03أي ثمانية بايتات زائد ثمانية بايتات مضروبة في ثلاثة،
00:03:05وهو ما يعادل 48 بايت إجمالاً،
00:03:07وثلاث عمليات تخصيص منفصلة للكومة.
00:03:09ولكن عندما نظروا في كيفية استخدام هذه القوائم
00:03:10في الواقع،
00:03:12أدركوا أنها تُقرأ دائماً معاً،
00:03:13وتُكتب دائماً معاً،
00:03:14كما أنها تأتي دائماً بنفس الترتيب تماماً.
00:03:16لذا بدلاً من ثلاث قوائم،
00:03:17يمكنهم التعامل معها كقائمة واحدة تحتوي على فاصلين بداخلها.
00:03:20وبذلك تتحول القوائم الثلاث إلى قائمة واحدة من السجلات،
00:03:22بالإضافة إلى إزاحتين صغيرتين تشيران إلى أن الإجابات تنتهي هنا،
00:03:25وأن المصدر ينتهي هنا،
00:03:26وبما أن استجابة نظام أسماء النطاقات لن تحتوي أبداً على أربعة مليارات سجل،
00:03:29فسيكون عدد صحيح غير سالْب مكون من 16 بتاً كافياً لقيم الإزاحة،
00:03:33وهو ما يمثل بايتين فقط لكل منهما.
00:03:34هذا يعني أنه في المجموع،
00:03:35لقد استبدلوا رأسين كاملين بحجم 16 بايت برقمين بحجم بايتين،
00:03:39وبالتالي تم توفير 28 بايت لكل مدخل،
00:03:41وهذا يتيح أيضاً للغة رست إزالة بعض الفراغات الإضافية بين الحقول،
00:03:44مما يجعل الهيكل (Struct) أصغر حجماً من الحقول التي تمت إزالتها وحدها.
00:03:47لقد طوّروا هذا المفاهيم أبعد من ذلك،
00:03:49ودمجوا العديد من حقول القيم البوليانية (Boolean) في علامة بت واحدة.
00:03:52بالانتقال إلى التغيير رقم ثلاثة،
00:03:53ماذا لو توقفنا عن ذكر نفس الاسم مرتين؟
00:03:55يحمل كل سجل من سجلات أسماء النطاقات مالكاً،
00:03:57وهو ببساطة اسم النطاق الذي ينتمي إليه هذا السجل.
00:04:00لذا فعندما تستعلم عن betterstack.com وتحصل على سجلاتك بالمقابل،
00:04:03يكون مكتوباً على كل سجل منها betterstack.com.
00:04:05ولكن هذه المعلومات تعد زائدة عن الحاجة نوعاً ما.
00:04:08أنت الشخص الذي طرح السؤال،
00:04:09لذا فهو يعرف اسم النطاق بالفعل.
00:04:11وكانت كلودفلير تخزن نطاق الاستعلام هذا بالفعل بمثابة مفتاح التخزين المؤقت،
00:04:14فلماذا يحتاجون إلى تخزينه مرة أخرى كمالك؟
00:04:17حسناً، إنهم لا يحتاجون إلى ذلك.
00:04:17لذا قامت كلودفلير ببساطة بتغيير هذا الحقل إلى اسم صندوق اختياري،
00:04:20حيث إنه إذا كان المالك يطابق الاستعلام،
00:04:22فلا تخزن شيئاً،
00:04:23ولكن إذا كان مختلفاً حقاً،
00:04:24وهو ما قد يكون عليه الحال في بعض الحالات مثل سلاسل CNAME،
00:04:27فإنك تخزن المالك تماماً كما كان من قبل.
00:04:29من خلال القيام بذلك، في الحالات العادية التي تتطابق فيها البيانات،
00:04:32فإنهم يوفرون عملية تخصيص كاملة للكومة لكل سجل،
00:04:34لذا كان هذا التوفير ببساطة مسألة إمعان النظر في البيانات الموجودة في التخزين المؤقت
00:04:37وإدراك وجود قيم مكررة.
00:04:39بالنسبة للتوفير رقم چهار، لدينا عنوان بروتوكول الإنترنت بحجم 144 بايت.
00:04:43كانت بيانات سجلاتهم عبارة عن تعداد (Enum) بلغة رست يتكون من سجلات A، وسجلات AAAA، والنصوص،
00:04:47و SVCB، و NAPTR، حيث يغطي نوع واحد جميع هذه الأنواع.
00:04:51ولكن هنا تكمن مشكلة الأنواع (Enums).
00:04:52فهي دائماً بحجم أكبر خيار فيها.
00:04:54تستهلك كل قيمة من ذلك النوع نفس القدر من المساحة،
00:04:57سواء كانت بحاجة إليها أم لا.
00:04:58في هذه الحالة، يعتبر NAPTR أكبر قيمة، حيث تبلغ مساحته 136 بايت،
00:05:03وعندما تضيف العلامة والحشوة إلى نوع البيانات الممتد (enum)، يصل الحجم إلى 144 بايت.
00:05:07إذا قارنت ذلك بما يحتاجه سجل A، وهو مجرد عنوان IPv4 بسيط،
00:05:12فسيحتاج إلى أربعة بايتات فقط.
00:05:13هذا يعني أن كل سجل A في هذا التخزين المؤقت كان قاعداً في صندوق بحجم 144 بايت،
00:05:17بينما يستخدم أربعة بايتات فقط،
00:05:19وسجلات A و 4A تمثل الجزء الأكبر من حركة المرور الحقيقية.
00:05:22في مزيج اختبار الأداء الخاص بـ Cloudflare، تشكل سجلات A نسبة 56%، و 25% لـ 4A، لذا كان غالبية التخزين المؤقت عبارة عن حشوة فقط.
00:05:29الحل لهذه المشكلة كان صندوقنا الموثوق.
00:05:32لقد قاموا بوضع المتغيرات الكبيرة في صناديق وأبقوا A و 4A ضمن الخط، لأنهما صغيران وشائعان،
00:05:36لذا أصبحت الآن text و SVCB و NAPTR خلف مؤشر،
00:05:40بحيث لا يجب أن يكون نوع البيانات الممتد أكبر من أكبر متغير متبقٍ، وهو عنوان IPv6 الذي يبلغ حجمه 16 بايت.
00:05:45إذن بالمجمل، بالنسبة لسجل A أو 4A، تم توفير 120 بايت لكل منهما.
00:05:50ولكن هذا التغيير يأتي مع مقايضة في الواقع.
00:05:52عندما تضع متغيراً في صندوق، تنتقل بياناته من التواجد داخل إدخال التخزين المؤقت،
00:05:55ليستقر في منطقة خاصة به على الكومة في مكان مختلف تماماً،
00:05:58وهذا يكلفك تكلفتين جديدتين.
00:06:00الأولى هي مخصص الذاكرة.
00:06:02تستخدم Cloudflare مخصص Gemalock، وهو لا يمنحك العدد الدقيق للبايتات التي تطلبها،
00:06:06بل يجمع التخصيصات في صناديق ذات أحجام ثابتة ويقرب الحجم إلى أقرب صندوق.
00:06:10لذا فإن سجل النص الذي يطلب 32 بايت ينتهي في صندوق بحجم 32 بايت ولا يهدر شيئاً،
00:06:15ولكن سجل MX يطلب 40، ويتم تقريبه إلى 48 بايت، وتفقد بهدوء 8 بايتات.
00:06:21التكلفة الثانية هي المجاورة في الذاكرة.
00:06:22قبل التخزين في صناديق، كانت كل بيانات السجلات لإدخال واحد تقع في كتلة ذاكرة متجاورة واحدة،
00:06:27وبعد التخزين في صناديق، يعيش كل منها في مكان آخر، وقراءته تعني تتبع مؤشر،
00:06:31وإذا وقع هذا المؤشر بعيداً عن بقية الإدخال،
00:06:34يجب على وحدة المعالجة المركزية الخاصة بك جلب خط ذاكرة مؤقتة جديد تماماً لمجرد قراءته.
00:06:37لذا، بينما أصلح وضع الصناديق مشكلة الحشوة، إلا أنه خلق مشكلة خاصة به،
00:06:41وهنا فكرت Cloudflare: ماذا لو لم نقم بتخزينها كأنواع بيانات Rust على الإطلاق؟
00:06:45حسنًا، هذا هو التغيير رقم خمسة.
00:06:46وصفته Cloudflare بأنه حل وسط: الاحتفاظ ببقية إدخال التخزين المؤقت كحقول منظمة عادية،
00:06:50ولكن أخذ بيانات السجل نفسها وتخزينها كبايتات خام.
00:06:54لذا، بدلاً من استخدام نوع ممتد أو صندوق لكل سجل، يحصل الإدخال بأكمله على مصفوفة بايتات واحدة مفردة،
00:07:00مع كتابة كل سجل كبادئة طول مكونة من بايتين، متبوعة ببياناته.
00:07:03هذا يلغي كلتا التكلفتين اللتين تحدثنا عنهما للتو.
00:07:06تندمج كل تخصيصات الصناديق المنفصلة هذه في تخصيص واحد لجميع بيانات السجلات،
00:07:10لذا لم يعد هناك تقريب لكل سجل لأعلى ليشمل صندوق Gemalock،
00:07:13وهي مرتبة بشكل متجاور مرة أخرى، لذا يمكنك استعادة تلك المجاورة في الذاكرة التي أخذها وضع الصناديق.
00:07:18وكفائدة إضافية، فإنه يجعل عمليات البحث أسرع أيضاً.
00:07:21في السابق، عند كل عملية تخزين مؤقت، كان لديك سجل محلل قاعد في الذاكرة،
00:07:25 وكان عليك تسلسله حقلًا تلو الآخر مرة أخرى إلى تنسيق سلك DNS قبل أن تتمكن من إرساله إلى أي مكان.
00:07:30الآن أصبح بالتنسيق الفعلي لسلك DNS، لذا يتم نسخ معظم أنواع السجلات مباشرة من المخزن المؤقت
00:07:35إلى الرسالة الصادرة.
00:07:37الوحيدة التي لا تزال بحاجة إلى تحليل هي السجلات التي تحتوي على أسماء نطاقات،
00:07:40لذا CNAME و NS و MX و SOA،
00:07:43وهذا فقط لأن ضغط أسماء DNS يعني أنه يتعين عليك إعادة كتابة تلك الأسماء على أي حال.
00:07:47لذا فإن هذا التغيير الأخير يقلل الذاكرة ويحذف عبئاً كبيراً من المسار الحرج.
00:07:51إذن ها نحن ذا، هذه 5 تغييرات منخفضة المستوى على التخزين المؤقت،
00:07:54والتي عند دمجها تقلل بصمة الذاكرة لكل إدخال من 953 بايت إلى 420،
00:08:00أي أصغر بنسبة 56%، وانخفضت الذاكرة المخصصة فعلياً لكل إدخال من 1.1 كيلوبايت
00:08:05إلى 461 بايت، بانخفاض نسبته 58%.
00:08:09علاوة على ذلك، ارتفعت سرعة إدخال البيانات بنسبة 43%،
00:08:12من 625,000 إدخال في الثانية إلى 893,000،
00:08:17وأصبحت عمليات البحث أسرع بنسبة 19%، منخفضة من 828 نانوثانية إلى 670.
00:08:23لقد نشروا هذه التغييرات عبر بيئة الإنتاج هذا العام،
00:08:25وانخفضت الذاكرة المقيمة P99 لديهم من 9.3 غيغابايت إلى 5.3،
00:08:29أي خفض بنسبة 43% على حركة المرور الحقيقية،
00:08:32وهو ما يعادل على مستوى الشبكة بأكملها تحرير ما يقريب من 100 تيرابايت من الذاكرة،
00:08:35أو ما يكفي من ذاكرة الوصول العشوائي لـ 130 خادماً من الجيل 13.
00:08:38الآن يخططون لاستخدام هذه المساحة الإضافية للحصول على ذاكرة مؤقتة أكبر،
00:08:41مما يجعل الأمور أسرع أكثر.
00:08:43تعجبني حقاً هذه المدونة لأنها تسلط الضوء على قرار سيتعين علينا اتخاذه.
00:08:46هل كان يجب أن نجلس قبل بناء أي من هذا ونعمل على كل التحسينات،
00:08:50أو لكان ذلك تحجيماً مبكراً جداً؟
00:08:52وأتخيل أنه في ذلك الوقت في عام 2018 عندما تم بناء هذا،
00:08:55لم تكن تكلفة ذاكرة الوصول العشوائي لـ Cloudflare بنفس الأهمية التي هي عليها اليوم.
00:08:59المقال بأكمله عبارة عن مقال رائع، لذا سأترك رابطه في الأسفل.
00:09:02أخبرني برأيك حول هذا في التعليقات،
00:09:03وبينما أنت هناك اشترك،
00:09:04وكالعادة، أراكم في الفيديو القادم.
00:09:05أراكم في الفيديو القادم.
Community Posts
No posts yet. Be the first to write about this video!
Write about this video