ضغط البيانات في Apache Ignite. تجربة سبير

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

لذلك، مع تمكين وضع الاستمرارية، نتيجة للتغيرات في البيانات الموجودة في ذاكرات التخزين المؤقت، يبدأ Ignite في الكتابة إلى القرص:

  1. محتويات المخابئ
  2. كتابة السجل المسبق (المشار إليه فيما يلي ببساطة بـ WAL)

لقد كانت هناك آلية لضغط WAL منذ بعض الوقت، تسمى ضغط WAL. قدم Apache Ignite 2.8 الذي تم إصداره مؤخرًا آليتين إضافيتين تسمحان لك بضغط البيانات الموجودة على القرص: ضغط صفحة القرص لضغط محتويات ذاكرة التخزين المؤقت وضغط لقطة صفحة WAL لضغط بعض إدخالات WAL. مزيد من التفاصيل حول هذه الآليات الثلاث أدناه.

ضغط صفحة القرص

كيف يعمل هذا؟

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

يتم تخزين البيانات على القرص بالشكل التالي: يتم إنشاء ملف منفصل لكل قسم من كل مجموعة ذاكرة تخزين مؤقت، وفي هذا الملف تظهر الصفحات واحدة تلو الأخرى بترتيب فهرس تصاعدي. يحتوي معرف الصفحة الكاملة على معرف مجموعة ذاكرة التخزين المؤقت ورقم القسم وفهرس الصفحة في الملف. وبالتالي، باستخدام معرف الصفحة الكاملة، يمكننا تحديد الملف والإزاحة في الملف لكل صفحة بشكل فريد. يمكنك قراءة المزيد حول ذاكرة الترحيل في مقالة Apache Ignite Wiki: متجر Ignite Persistent Store - تحت الغطاء.

تعمل آلية ضغط صفحة القرص، كما قد يتبادر إلى ذهنك من الاسم، على مستوى الصفحة. عند تمكين هذه الآلية، تتم معالجة البيانات الموجودة في ذاكرة الوصول العشوائي (RAM) كما هي، دون أي ضغط، ولكن عندما يتم حفظ الصفحات من ذاكرة الوصول العشوائي (RAM) إلى القرص، يتم ضغطها.

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

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

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

من المنطقي أنه من أجل تحرير كتلة نظام الملفات، يجب أن يكون حجم الثغرة أكبر من أو يساوي كتلة نظام الملفات، مما يفرض قيودًا إضافية على حجم الصفحة وApache Ignite: لكي يكون للضغط أي تأثير، يجب أن يكون حجم الصفحة أكبر تمامًا من حجم كتلة نظام الملفات. إذا كان حجم الصفحة مساويًا لحجم الكتلة، فلن نتمكن أبدًا من تحرير كتلة واحدة، لأنه من أجل تحرير كتلة واحدة، يجب أن تشغل الصفحة المضغوطة 0 بايت. إذا كان حجم الصفحة يساوي حجم كتلتين أو أربع كتل، فسنكون قادرين بالفعل على تحرير كتلة واحدة على الأقل إذا تم ضغط صفحتنا إلى 2% أو 4% على الأقل، على التوالي.

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

ضغط البيانات في Apache Ignite. تجربة سبير

في التطبيق الحالي، يمكن لـ Ignite العمل فقط مع الملفات المتفرقة ضمن نظام التشغيل Linux؛ وبالتالي، لا يمكن تمكين ضغط صفحات القرص إلا عند استخدام Ignite على نظام التشغيل هذا.

خوارزميات الضغط التي يمكن استخدامها لضغط صفحات القرص: ZSTD، LZ4، Snappy. بالإضافة إلى ذلك، يوجد وضع التشغيل (SKIP_GARBAGE)، حيث يتم التخلص فقط من المساحة غير المستخدمة في الصفحة دون الضغط على البيانات المتبقية، مما يقلل الحمل على وحدة المعالجة المركزية مقارنة بالخوارزميات المذكورة مسبقًا.

تأثير الأداء

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

للقيام بذلك، علينا أن نتذكر كيفية قراءة الصفحات وكتابتها عند الوصول إليها:

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

وبالتالي فإن التأثير على عمليات القراءة هو:

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

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

كيفية تمكين وتكوين

كما ذكرنا سابقًا، الحد الأدنى لإصدار Apache Ignite الذي يدعم ضغط صفحات القرص هو 2.8 ويتم دعم نظام التشغيل Linux فقط. تمكين وتكوين على النحو التالي:

  • يجب أن تكون هناك وحدة ضغط الإشعال في مسار الفصل. بشكل افتراضي، فهو موجود في توزيع Apache Ignite في الدليل libs/الاختياري ولا يتم تضمينه في مسار الفئة. يمكنك ببساطة نقل الدليل إلى مستوى أعلى إلى libs وبعد ذلك عند تشغيله من خلال ignite.sh سيتم تمكينه تلقائيًا.
  • يجب تمكين الثبات (ممكّن عبر DataRegionConfiguration.setPersistenceEnabled(true)).
  • يجب أن يكون حجم الصفحة أكبر من حجم كتلة نظام الملفات (يمكنك ضبطه باستخدام DataStorageConfiguration.setPageSize() ).
  • لكل ذاكرة تخزين مؤقت تحتاج بياناتها إلى الضغط، يجب عليك تكوين طريقة الضغط و(اختياريًا) مستوى الضغط (الطرق) CacheConfiguration.setDiskPageCompression() , CacheConfiguration.setDiskPageCompressionLevel()).

ضغط وول

كيف يعمل هذا؟

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

تنقسم الإدخالات في WAL إلى منطقية ومادية. تلك المنطقية هي المفاتيح والقيم نفسها. فعلي - يعكس التغييرات التي تم إجراؤها على الصفحات في متجر الصفحات. في حين أن السجلات المنطقية يمكن أن تكون مفيدة لبعض الحالات الأخرى، إلا أن السجلات الفعلية مطلوبة فقط للاسترداد في حالة حدوث عطل وتكون السجلات مطلوبة فقط منذ آخر نقطة تفتيش ناجحة. هنا لن نخوض في التفاصيل ونشرح سبب عملها بهذه الطريقة، ولكن يمكن للمهتمين الرجوع إلى المقالة المذكورة سابقًا على Apache Ignite Wiki: متجر Ignite Persistent Store - تحت الغطاء.

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

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

ضغط البيانات في Apache Ignite. تجربة سبير

تأثير الأداء

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

كيفية تمكين وتكوين

يمكنك تمكين ضغط WAL باستخدام الخاصية WalCompactionEnabled в DataStorageConfiguration (DataStorageConfiguration.setWalCompactionEnabled(true)). أيضًا، باستخدام أسلوب DataStorageConfiguration.setWalCompactionLevel()، يمكنك ضبط مستوى الضغط إذا لم تكن راضيًا عن القيمة الافتراضية (BEST_SPEED).

ضغط لقطة صفحة WAL

كيف يعمل هذا؟

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

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

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

كما هو الحال مع ضغط صفحة القرص، يمكن لضغط لقطة صفحة WAL استخدام خوارزميات الضغط ZSTD وLZ4 وSnapy، بالإضافة إلى وضع SKIP_GARBAGE.

تأثير الأداء

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

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

بشكل غير مباشر، يؤثر تقليل حجم WAL أيضًا (إيجابيًا) على التدفقات التي تفرغ مقاطع WAL في الأرشيف وتدفقات ضغط WAL.

أظهرت اختبارات الأداء الحقيقية في بيئتنا باستخدام البيانات الاصطناعية زيادة طفيفة (زيادة الإنتاجية بنسبة 10%-15%، وانخفاض زمن الوصول بنسبة 10%-15%).

كيفية تمكين وتكوين

الحد الأدنى لإصدار Apache Ignite: 2.8. تمكين وتكوين على النحو التالي:

  • يجب أن تكون هناك وحدة ضغط الإشعال في مسار الفصل. بشكل افتراضي، فهو موجود في توزيع Apache Ignite في الدليل libs/الاختياري ولا يتم تضمينه في مسار الفئة. يمكنك ببساطة نقل الدليل إلى مستوى أعلى إلى libs وبعد ذلك عند تشغيله من خلال ignite.sh سيتم تمكينه تلقائيًا.
  • يجب تمكين الثبات (ممكّن عبر DataRegionConfiguration.setPersistenceEnabled(true)).
  • يجب ضبط وضع الضغط باستخدام الطريقة DataStorageConfiguration.setWalPageCompression()، يتم تعطيل الضغط افتراضيًا (وضع التعطيل).
  • اختياريًا، يمكنك ضبط مستوى الضغط باستخدام هذه الطريقة DataStorageConfiguration.setWalPageCompression()راجع javadoc لمعرفة طريقة القيم الصالحة لكل وضع.

اختتام

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

المصدر: www.habr.com

إضافة تعليق