الانتقال إلى المحتوى الرئيسي

المقدمة

يعالج ClickHouse الاستعلامات بسرعة فائقة، لكن كيف تُوزَّع هذه الاستعلامات ويُنفَّذ تنفيذها بالتوازي عبر عدة خوادم؟
في هذا الدليل، سنناقش أولًا كيف يوزّع ClickHouse الاستعلام عبر عدة شظايا من خلال الجداول الموزعة، ثم كيف يمكن للاستعلام أن يستفيد من عدة نُسخ متماثلة أثناء تنفيذه.

البنية المُجزّأة

في بنية shared-nothing، تُقسَّم العناقيد عادةً إلى عدة شظايا، بحيث تحتوي كل شظية على مجموعة فرعية من إجمالي البيانات. ويعلو هذه الشظايا جدول موزّع، يوفّر عرضًا موحّدًا لكامل البيانات. يمكن إرسال عمليات القراءة إلى الجدول المحلي. وفي هذه الحالة، لن يُنفَّذ الاستعلام إلا على الشظية المحددة. أو يمكن إرساله إلى الجدول الموزّع، وعندها ستنفّذ كل شظية الاستعلامات المطلوبة. وسيقوم الخادم الذي تم الاستعلام من خلاله عن الجدول الموزّع بتجميع البيانات وإرجاع الرد إلى العميل: يوضح الشكل أعلاه ما يحدث عندما يرسل عميل استعلامًا إلى جدول موزّع:
  1. يُرسل استعلام SELECT إلى جدول موزّع على إحدى العقد بشكل عشوائي (باستخدام استراتيجية التناوب أو بعد توجيهه إلى خادم محدد بواسطة موازن تحميل). وستعمل هذه العقدة الآن كمنسّق.
  2. ستحدّد العقدة كل شظية تحتاج إلى تنفيذ الاستعلام استنادًا إلى المعلومات التي يحددها الجدول الموزّع، ثم يُرسل الاستعلام إلى كل شظية.
  3. تقرأ كل شظية البيانات وتُرشّحها وتُجمّعها محليًا، ثم ترسل حالة قابلة للدمج إلى المنسّق.
  4. تدمج العقدة المنسِّقة البيانات ثم ترسل الاستجابة إلى العميل.
عند إضافة النسخ المتماثلة إلى هذا المزيج، تبقى العملية متشابهة إلى حد كبير، ويكمن الفرق الوحيد في أن نسخة متماثلة واحدة فقط من كل شظية ستنفّذ الاستعلام. وهذا يعني أنه يمكن بعد ذلك معالجة المزيد من الاستعلامات بالتوازي.

بنية غير مُشظّاة

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

تقديم النسخ المتماثلة المتوازية

لموازاة تنفيذ الاستعلام عبر عدة خوادم، نحتاج أولًا إلى القدرة على تعيين أحد خوادمنا بصفته منسّقًا. والمنسّق هو العقدة التي تنشئ قائمة المهام التي يجب تنفيذها، وتضمن تنفيذها جميعًا، وتجميع نتائجها وإرجاعها إلى العميل. وكما هو الحال في معظم الأنظمة الموزعة، يكون هذا دور العقدة التي تستقبل الاستعلام الأولي. ونحتاج أيضًا إلى تحديد وحدة العمل. في بنية تعتمد على الشظايا، تكون وحدة العمل هي الـشظية، أي مجموعة فرعية من البيانات. ومع النسخ المتماثلة المتوازية سنستخدم جزءًا صغيرًا من الجدول، يُسمى الحبيبات، بوصفه وحدة العمل. والآن، لنرَ كيف يعمل ذلك عمليًا بمساعدة الشكل أدناه: مع النسخ المتماثلة المتوازية:
  1. يُرسَل الاستعلام من العميل إلى عقدة واحدة بعد مروره عبر موازن تحميل. وتصبح هذه العقدة المنسّق لهذا الاستعلام.
  2. تحلّل العقدة فهرس كل جزء، وتحدّد الأجزاء والحبيبات المناسبة للمعالجة.
  3. يقسّم المنسّق عبء العمل إلى مجموعة من الحبيبات التي يمكن إسنادها إلى نسخ متماثلة مختلفة.
  4. تُعالَج كل مجموعة من الحبيبات بواسطة النسخ المتماثلة المقابلة لها، وتُرسَل حالة قابلة للدمج إلى المنسّق عند الانتهاء.
  5. أخيرًا، يدمج المنسّق جميع نتائج النسخ المتماثلة ثم يعيد النتيجة إلى العميل.
توضّح الخطوات أعلاه كيفية عمل النسخ المتماثلة المتوازية من الناحية النظرية. ومع ذلك، عمليًا، هناك كثير من العوامل التي قد تمنع هذه الآلية من العمل على نحو مثالي:
  1. قد تكون بعض النسخ المتماثلة غير متاحة.
  2. تكون آلية النسخ المتماثل في ClickHouse غير متزامنة، وقد لا تحتوي بعض النسخ المتماثلة على الأجزاء نفسها في لحظة معينة.
  3. يجب التعامل مع كمون الذيل بين النسخ المتماثلة.
  4. تختلف ذاكرة التخزين المؤقت لنظام الملفات من نسخة متماثلة إلى أخرى بحسب النشاط على كل نسخة متماثلة، ما يعني أن إسناد المهام عشوائيًا قد يؤدي إلى أداء أقل كفاءة نظرًا إلى محلية ذاكرة التخزين المؤقت.
نستعرض في الأقسام التالية كيفية تجاوز هذه العوامل.

الإعلانات

لمعالجة (1) و(2) من القائمة أعلاه، قدّمنا مفهوم الإعلان. لنتصوّر كيف يعمل ذلك باستخدام الشكل أدناه:
  1. يُرسَل الاستعلام من العميل إلى إحدى العُقد بعد مروره عبر موازن التحميل. وتصبح هذه العقدة المنسّق لهذا الاستعلام.
  2. ترسل العقدة المنسِّقة طلبًا للحصول على إعلانات من جميع النسخ المتماثلة في العنقود. وقد تكون لدى النسخ المتماثلة تصوّرات مختلفة قليلًا عن المجموعة الحالية من الأجزاء في جدولٍ ما. لذلك نحتاج إلى جمع هذه المعلومات لتجنّب اتخاذ قرارات جدولة غير صحيحة.
  3. تستخدم العقدة المنسِّقة بعد ذلك الإعلانات لتحديد مجموعة من الحبيبات التي يمكن إسنادها إلى النسخ المتماثلة المختلفة. هنا، على سبيل المثال، نرى أنه لم تُسنَد أي حبيبات من الجزء 3 إلى النسخة المتماثلة 2 لأن هذه النسخة المتماثلة لم تُدرِج هذا الجزء في إعلانها. ولاحظ أيضًا أنه لم تُسنَد أي مهام إلى النسخة المتماثلة 3 لأن هذه النسخة لم تقدّم إعلانًا.
  4. بعد أن تعالج كل نسخة متماثلة الاستعلام على مجموعتها الفرعية من الحبيبات وتُرسَل الحالة القابلة للدمج مرة أخرى إلى المنسّق، يدمج المنسّق النتائج ثم يُرسَل الرد إلى العميل.

التنسيق الديناميكي

لمعالجة مشكلة كمون الذيل، أضفنا التنسيق الديناميكي. ويعني ذلك أن الحبيبات لا تُرسَل كلها إلى نسخة متماثلة ضمن طلب واحد، بل تتمكن كل نسخة متماثلة من طلب مهمة جديدة (أي مجموعة من الحبيبات المطلوب معالجتها) من المنسّق. ويزوّد المنسّق النسخة المتماثلة بمجموعة الحبيبات بناءً على الإعلان الذي تلقّاه. لنفترض أننا وصلنا إلى مرحلة من العملية تكون فيها جميع النسخ المتماثلة قد أرسلت إعلانًا يتضمن جميع الأجزاء. يوضّح الشكل أدناه كيفية عمل التنسيق الديناميكي:
  1. تُبلغ النسخ المتماثلة عقدة المنسّق بأنها قادرة على معالجة المهام، ويمكنها أيضًا تحديد مقدار العمل الذي تستطيع معالجته.
  2. يوزّع المنسّق المهام على النسخ المتماثلة.
  1. تتمكن النسختان المتماثلتان 1 و2 من إنهاء مهمتهما بسرعة كبيرة، لذا تطلبان مهمة أخرى من عقدة المنسّق.
  2. يوزّع المنسّق مهامًا جديدة على النسختين المتماثلتين 1 و2.
  1. تكون جميع النسخ المتماثلة قد انتهت الآن من معالجة مهامها. وتطلب المزيد من المهام.
  2. يتحقق المنسّق، باستخدام الإعلانات، من المهام التي لا تزال بحاجة إلى معالجة، لكنه لا يجد أي مهام متبقية.
  3. يُبلغ المنسّق النسخ المتماثلة بأن كل شيء قد تمت معالجته. وسيقوم الآن بدمج جميع الحالات القابلة للدمج والرد على الاستعلام.

إدارة محلية ذاكرة التخزين المؤقت

آخر مشكلة محتملة متبقية هي كيفية التعامل مع محلية ذاكرة التخزين المؤقت. إذا نُفِّذ الاستعلام عدة مرات، فكيف نضمن توجيه المهمة نفسها إلى النسخة المتماثلة نفسها؟ في المثال السابق، كانت المهام موزعة على النحو التالي:
النسخة المتماثلة 1النسخة المتماثلة 2النسخة المتماثلة 3
الجزء 1g1, g6, g7g2, g4, g5g3
الجزء 2g1g2, g4, g5g3
الجزء 3g1, g6g2, g4, g5g3
ولضمان إسناد المهام نفسها إلى النسخ المتماثلة نفسها بحيث تستفيد من ذاكرة التخزين المؤقت، يحدث أمران. أولًا، تُحتسب قيمة hash للجزء + مجموعة الحبيبات (أي المهمة). ثانيًا، يُطبَّق باقي قسمة عدد النسخ المتماثلة لتحديد إسناد المهمة. نظريًا يبدو هذا جيدًا، لكن عمليًا قد يتسبب حمل مفاجئ على إحدى النسخ المتماثلة، أو تدهور في الشبكة، في زيادة زمن الاستجابة عند الذيل إذا استُخدمت النسخة المتماثلة نفسها باستمرار لتنفيذ مهام معينة. إذا كانت قيمة max_parallel_replicas أقل من عدد النسخ المتماثلة، فستُختار نسخ متماثلة عشوائية لتنفيذ الاستعلام.

استيلاء المهام

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

القيود

لهذه الميزة قيود معروفة، وقد وُثِّقت أهمها في هذا القسم.
إذا صادفت مشكلة لا تندرج ضمن القيود المذكورة أدناه، وتشتبه في أن النسخة المتماثلة المتوازية هي السبب، يُرجى فتح issue على GitHub باستخدام الوسم comp-parallel-replicas.

استقصاء المشكلات المتعلقة بالنسخ المتماثلة المتوازية

يمكنك التحقق من الإعدادات المستخدمة لكل query في جدول system.query_log. ويمكنك أيضًا الاطلاع على جدول system.events لرؤية جميع الأحداث التي حدثت على الخادم، كما يمكنك استخدام table function clusterAllReplicas لرؤية الجداول على جميع النسخ المتماثلة (إذا كنت من مستخدمي Cloud، فاستخدم default).
Query
Response
يتضمن جدول system.text_log أيضًا معلومات عن تنفيذ الاستعلامات باستخدام النسخ المتماثلة المتوازية:
Query
Response
أخيرًا، يمكنك أيضًا استخدام EXPLAIN PIPELINE. يوضّح هذا كيف سيُنفِّذ ClickHouse الاستعلام والموارد التي سيستخدمها في تنفيذه. لنأخذ الاستعلام التالي مثالًا:
لنلقِ نظرة على مسار تنفيذ الاستعلام بدون استخدام parallel replica:
EXPLAIN PIPELINE (without parallel replica)
والآن مع النسخ المتماثلة المتوازية:
EXPLAIN PIPELINE (with parallel replica)
آخر تعديل في ٢ يوليو ٢٠٢٦