نشر فريق Netflix الهندسي طريقة للتعامل مع الأقسام الواسعة في Apache Cassandra. يستهدف العمل البحثي TimeSeries Abstraction من Netflix، وهي منصة لبيانات الأحداث الزمنية.

ليرة تركية؛ د

  • يقوم التقسيم الديناميكي بتقسيم أقسام Cassandra الواسعة لكل معرف TimeSeries، بشكل غير متزامن وشفاف، دون أي تغييرات في التطبيق.
  • يعمل الكشف على مسار القراءة عبر عد البايتات وحدث كافكا؛ يستهدف التقسيم الأقسام غير القابلة للتغيير أولاً.
  • مرشحات بلوم (ميكروثانية من رقم واحد) بالإضافة إلى ذاكرة التخزين المؤقت wide_row يقرأ مسار البحث عن بيانات التعريف إلى الأقسام الفرعية الأصغر.
  • المجاميع الاختبارية، والأقسام الأصلية المحتجزة، وفحوصات Data Bridge Spark، وصحة حماية مقارنة الظل.
  • تم تحسين القراءات من الثواني إلى المللي ثانية المنخفضة المكونة من رقمين؛ انخفض زمن الوصول إلى حوالي 200 مللي ثانية؛ بقي 500 ميجا بايت + أقسام متاحة.

ما هو إعادة التقسيم الديناميكي؟

يقوم برنامج TimeSeries Abstraction الخاص بـ Netflix باستيعاب واستعلام عن بيتابايت من بيانات الأحداث المؤقتة مع زمن استجابة بالمللي ثانية. ويستخدم Apache Cassandra 4.x كمخزن أساسي. تم اختيار Cassandra من حيث الإنتاجية وزمن الوصول والتكلفة والنضج التشغيلي.

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

لماذا تؤذي الأقسام الواسعة القراءات

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

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

استراتيجية التقسيم وراء السلاسل الزمنية

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

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

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

الحل 1: إعادة تقسيم شريحة الوقت

تكشف كاساندرا عن واجهات برمجة التطبيقات الاستبطانية مثل nodetool tablehistograms للنسب المئوية لحجم القسم. يقوم عامل الخلفية بمراقبة هذه الرسوم البيانية ويعرضها من خلال جدول Cassandra الافتراضي. فهو يحسب عامل التعديل عندما تفوت أحجام الأقسام كثافة مكونة. غالبًا ما يتم ضبط هذه الكثافة بين 2 MiB و10 MiB، اعتمادًا على حجم العمل.

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

DynamicTimeSliceConfigWorker:
namespace: my_dataset_1
Observed: TimeSlices have p99 partitions below configured target of 10MB.
Proposed: time_bucket interval: 60s -> 604800s

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

  • لا تفعل شيئًا: النهج الصحيح عندما لا تظهر مقاييس المستوى الأعلى أي تأثير.
  • العوائد الجزئية: يلغي طلبًا أثناء الرحلة يخرق SLO لزمن الاستجابة، ويعيد البيانات التي تم جمعها حتى الآن.
  • معرفات الحظر: خطوة متطرفة لمعرفات الاختبار أو البريد العشوائي التي تزعزع استقرار النظام.

يتم تطبيق معرفات الحظر من خلال التكوين، مع إدراج معرفات TimeSeries المخالفة:

dgwts.config.<dataset>.block.Ids: "<tsid-1>, <tsid-2>, <tsid-3>"

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

الحل 2: التقسيم الديناميكي لكل معرف

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

كشف يحدث على مسار القراءة. كل قراءة تتعقب البايتات المقروءة لقسم ما. عندما تتجاوز البايتات الحد المكوّن، يرسل الخادم حدثًا إلى Kafka:

{
  "time_slice": "data_20260328",
  "time_series_id": "profileId:123",
  "time_bucket": 7,
  "event_bucket": 2,
  "immutable": true,
  "version": "0"
}

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

تخطيط يقرأ القسم بأكمله مرة واحدة لحساب خطة تقسيم دقيقة. يتيح Checkpointing استئناف قراءات التخطيط الفاشلة من آخر نقطة محفوظة. ال wide_row يقوم جدول بيانات التعريف بتخزين الحالات المقسمة ونقاط التفتيش ومعلومات التوجيه.

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

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

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

{
  "pre_split_data": {
    "time_slice": "data_20260328",
    "time_series_id": "6313825",
    "time_bucket": 0,
    "event_bucket": 2
  },
  "post_split_data": {
    "time_slice": "wide_data_20260328_0",
    "event_bucket_partition_strategy": {
      "target_event_buckets": 2,
      "start_event_bucket": 32
    }
  }
}

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

قام فريق Netflix أيضًا بالتحقق من الانقسامات دون الاتصال بالإنترنت باستخدام وظائف Data Bridge Spark. تقدم الطرح المرحلي من خلال أوضاع القراءة مع نمو الثقة. تقوم مرحلة المقارنة الخاصة بها بمقارنة البايتات التي تخدمها مسارات القراءة القديمة والجديدة في وضع الظل.

الحل 1 مقابل الحل 2: المقارنة

البعد إعادة تقسيم شريحة الوقت (الحل 1) التقسيم الديناميكي لكل معرف (الحل 2)
التفاصيل الجدول / مستوى شريحة الوقت مستوى معرف TimeSeries الفردي
مشغل عامل الخلفية على الرسوم البيانية التقسيم تتجاوز وحدات البايت المقروءة حدًا على مسار القراءة
نطاق التأثير شرائح الزمن المستقبلي فقط توجد أقسام واسعة غير قابلة للتغيير
الآلية الأساسية يُعدِّل time_bucket الفاصل الزمني / كثافة الهدف انقسم إلى أقسام دلو الأحداث التابعة
إشارة الكشف nodetool tablehistograms النسب المئوية عد البايت لكل قراءة، حدث كافكا
الأفضل متى تم تقسيم معظم الجدول بشكل خاطئ بعض المعرفات هي قيم متطرفة واسعة
حركة البيانات لا أحد؛ ينطبق على الكتابات الجديدة تقسيم غير متزامن؛ تم الاحتفاظ بالأصل كاحتياطي
الهدف / التحقق من الصحة الكثافة المكونة (2–10 ميجابايت) المجموع الاختباري قبل/بعد الانقسام + مقارنة الظل

استخدام الحالات مع الأمثلة

  • سجلات نشاط المستخدم طويلة الأمد: أ profileId:123 تراكم سنوات من أحداث التشغيل يصبح واسعًا. يقوم الحل 2 بتوزيعه عبر مجموعات الأحداث، بحيث يظل ترقيم الصفحات متاحًا. قام Netflix بتقسيم صفحات بحجم 500 ميجابايت+ بينما يظل متاحًا باستخدام هذا المسار.
  • القياس عن بعد للجهاز أو إنترنت الأشياء: مجموعة صغيرة من أجهزة الدردشة تهيمن على حجم الحدث. يقوم الحل 2 بعزل تلك المعرفات الساخنة دون إعادة تقسيم الجدول بأكمله.
  • الإفراط في توفير مجموعة البيانات الجديدة: يخمن الفريق مجموعات مدتها 60 ثانية ويحصل على أقسام أقل من 10 كيلوبايت. يعمل الحل 1 على توسيع الفاصل الزمني لشرائح الوقت المستقبلية، مما يؤدي إلى قطع تضخيم القراءة.
  • لوحات المعلومات الحساسة لزمن الوصول: يحتاج المتصل إلى استجابة سريعة أكثر من البيانات الكاملة. تعمل عمليات الإرجاع الجزئية على تحديد زمن الوصول في SLO وإرجاع ما تم جمعه.

جربه: عرض الفاصل التفاعلي

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

نتائج

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

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

{
  "next_page_token": "...",
  "records": [ { "...": "..." } ],
  "response_context": [
    {
      "namespace": "...",
      "time_taken": "41.072410142s"
    }
  ]
}

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


تحقق من التفاصيل الفنية هنا. أيضا، لا تتردد في متابعتنا على تغريد ولا تنسى الانضمام إلينا 150 ألف + مل والاشتراك في النشرة الإخبارية لدينا. انتظر! هل أنت على برقية؟ الآن يمكنك الانضمام إلينا على التليجرام أيضًا.

هل تحتاج إلى الشراكة معنا للترويج لصفحة GitHub Repo أو صفحة الوجه المعانقة أو إصدار المنتج أو الندوة عبر الويب وما إلى ذلك؟ تواصل معنا



اكتشاف المزيد من كحيل | أخبار التقنية

اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.

شاركها.
اترك تعليقاً

اكتشاف المزيد من كحيل | أخبار التقنية

اشترك الآن للاستمرار في القراءة والحصول على حق الوصول إلى الأرشيف الكامل.

متابعة القراءة