الكاش والإخلاء: عندما يمتلئ الصندوق السحري – دليل شامل لخوارزميات التخزين المؤقت

استمع للبودكاست حوار شيق بين لمى وأبو عمر
0:00 / 0:00

الكاش والإخلاء: عندما يمتلئ الصندوق السحري

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

التخزين المؤقت (Caching) هو ببساطة طريقة لتخزين البيانات المستخدمة بشكل متكرر في مكان أسرع من مصدرها الأصلي (زي قاعدة البيانات أو القرص الصلب). تخيل الكاش زي صندوق سحري بتحط فيه الأشياء اللي بتستخدمها دايماً، عشان توصلها بسرعة بدل ما تروح تدور عليها كل مرة.

لكن الصندوق السحري مش كبير، ولازم نفضي مكان للأشياء الجديدة. هون بيجي دور “سياسات الإخلاء” (Eviction Policies): لما يمتلئ الكاش، أي البيانات لازم نحذفها عشان نفتح مجال لبيانات جديدة؟

خوارزميات الإخلاء الأساسية

في كتير خوارزميات، بس رح نركز على الأساسية والأكثر استخداماً:

LRU (Least Recently Used) – الأقل استخداماً مؤخراً

هاي الخوارزمية بسيطة ومنطقية. بتفترض إنه البيانات اللي استخدمناها مؤخراً، رح نستخدمها مرة تانية قريباً. يعني، بتحافظ على البيانات “الطازة” وبترمي القديمة.

الآلية:

  • بتحتفظ بقائمة مرتبة بالعناصر.
  • لما نوصل لعنصر، بننقله لبداية القائمة (يعني بنخليه “الأحدث”).
  • لما يمتلئ الكاش، بنحذف العنصر الموجود في نهاية القائمة (الأقدم).

# مثال بسيط لـ LRU في Python
from collections import OrderedDict

class LRUCache:
    def __init__(self, capacity: int):
        self.capacity = capacity
        self.cache = OrderedDict()

    def get(self, key: int) -> int:
        if key not in self.cache:
            return -1
        else:
            self.cache.move_to_end(key) # تحديث آخر استخدام
            return self.cache[key]

    def put(self, key: int, value: int) -> None:
        if key in self.cache:
            self.cache[key] = value
            self.cache.move_to_end(key)
        else:
            self.cache[key] = value
            if len(self.cache) > self.capacity:
                self.cache.popitem(last=False) # حذف الأقدم

نقاط الضعف:

بتعاني بشدة في حالات “المسح الشامل” (Full Scans). تخيل إنك بتعمل تقرير بيقرا قاعدة البيانات كلها مرة وحدة. الـ LRU رح تطرد كل البيانات المهمة والمتكررة من الكاش، وتحط بدالها بيانات التقرير اللي ما رح تستخدمها مرة تانية. هيك التطبيق رح يصير أبطأ (Cache Pollution).

نصيحة من أبو عمر: قبل ما تستخدم LRU، فكر منيح بطبيعة البيانات اللي بتتعامل معها. لو عندك عمليات مسح شاملة، يمكن مش الخيار الأفضل.

LFU (Least Frequently Used) – الأقل استخداماً

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

المزايا:

  • مقاومة لعمليات المسح الشامل، لأنه البيانات الجديدة اللي بنستخدمها مرة وحدة بس، العداد تبعها رح يكون قليل (1)، فما رح تطرد البيانات المهمة اللي العداد تبعها عالي.

العيوب:

  • معقدة التنفيذ، وبتستهلك ذاكرة إضافية عشان نحفظ العدادات لكل عنصر.
  • بتعاني من “التقادم” (Staleness): عنصر كان مشهور جداً الأسبوع الماضي، رح يضل بالكاش حتى لو ما عدنا بحاجته اليوم، لأنه العداد تبعه عالي.

نصيحة من أبو عمر: الـ LFU بتنفع لما يكون عندك بيانات بتتكرر كتير، بس بدك تنتبه لمشكلة التقادم. ممكن تستخدم طريقة عشان تقلل قيمة العدادات مع مرور الوقت (Aging) عشان تحل هاي المشكلة.

W-TinyLFU: أحدث التقنيات في عالم الكاش

الـ W-TinyLFU (Window TinyLFU) هي أحدث ما توصلت إليه هندسة الكاش، وهي مستخدمة في مكتبات قوية زي Caffeine (Java) و Ristretto (Go).

فلسفة القبول (Admission Policy):

بدل ما نقبل أي عنصر جديد بالكاش، الـ TinyLFU بتسأل: “هل هذا العنصر الجديد بستاهل نخزنه أكثر من العنصر اللي رح نطرده؟”. بتستخدم مخطط Count-Min Sketch (هيكل احتمالي) عشان تقدر التكرار بذاكرة قليلة جداً.

تصميم النافذة (Window Design):

الـ W-TinyLFU بتتكون من قسمين:

  • نافذة صغيرة (LRU): بتستقبل العناصر الجديدة وبتعطيها فرصة تثبت شعبيتها (بتحل مشكلة LFU مع العناصر الجديدة).
  • الكاش الرئيسي (SLRU): بيتم ترقية العناصر إليه بناءً على التكرار المقدر بواسطة TinyLFU.

النتيجة:

معدل إصابة (Hit Rate) بيقارب المثالية، مع حماية ضد التلوث ومقاومة للمسح الشامل.

نصيحة من أبو عمر: لو بتدور على حل كاش قوي وحديث، الـ W-TinyLFU خيار ممتاز. صحيح إنه تنفيذه معقد، بس المكتبات الجاهزة بتسهل الموضوع.

الخلاصة

اختيار خوارزمية الإخلاء المناسبة بيعتمد على طبيعة التطبيق والبيانات اللي بتتعامل معها. الـ LRU بسيطة وسريعة، بس بتعاني من المسح الشامل. الـ LFU أفضل في حالات التكرار، بس بدها ذاكرة إضافية. الـ W-TinyLFU هي الأحدث والأكثر تطوراً، بس تنفيذها معقد. 💡

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

أبو عمر

سجل دخولك لعمل نقاش تفاعلي

كافة المحادثات خاصة ولا يتم عرضها على الموقع نهائياً

آراء من النقاشات

لا توجد آراء منشورة بعد. كن أول من يشارك رأيه!

آخر المدونات

ذكاء اصطناعي

بحثنا كان يعثر على الكلمات، لا على النوايا: كيف أنقذتنا قواعد بيانات المتجهات من جحيم البحث الدلالي الأعمى؟

أشارككم قصة من قلب المعركة البرمجية، يوم كان نظام البحث لدينا أصمًا وأعمى، لا يفهم سوى تطابق الكلمات. سنغوص في عالم قواعد بيانات المتجهات (Vector...

14 أبريل، 2026 قراءة المزيد
خوارزميات

قاعدة بياناتنا كانت تجيب على ‘هل هذا موجود؟’ ببطء قاتل: كيف أنقذنا ‘مرشح بلوم’ (Bloom Filter) من جحيم الاستعلامات المكلفة؟

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

14 أبريل، 2026 قراءة المزيد
تجربة المستخدم والابداع البصري

موقعنا كان يستبعد الملايين بصمت: كيف أنقذتنا ‘معايير الوصولية’ (Accessibility) من جحيم التصميم الإقصائي؟

أشارككم قصة حقيقية حول كيف اكتشفنا أن تصميم موقعنا "الرائع" كان يقصي ملايين المستخدمين دون علمنا. هذه المقالة ليست مجرد سرد تقني، بل هي رحلة...

14 أبريل، 2026 قراءة المزيد
برمجة وقواعد بيانات

استعلاماتنا كانت تزحف: كيف أنقذتنا ‘فهارس قاعدة البيانات’ من جحيم فحص الجداول الكاملة؟

أشارككم قصة حقيقية من قلب المعركة البرمجية، حين كاد تطبيقنا أن ينهار بسبب بطء الاستعلامات. اكتشفوا معنا كيف كانت "فهارس قاعدة البيانات" هي طوق النجاة...

14 أبريل، 2026 قراءة المزيد
الشبكات والـ APIs

أنظمتنا كانت تسأل ‘هل هناك جديد؟’ كل ثانية: كيف أنقذتنا ‘الخطافات الشبكية’ (Webhooks) من جحيم الاستقصاء المستمر (Polling)؟

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

14 أبريل، 2026 قراءة المزيد
الحوسبة السحابية

تطبيقنا كان رهينة منطقة جغرافية واحدة: كيف أنقذتنا استراتيجية ‘متعددة المناطق’ (Multi-Region) من جحيم الانقطاع الكامل؟

أشارككم قصة حقيقية عن يوم توقف فيه تطبيقنا بالكامل بسبب انقطاع في منطقة سحابية واحدة، وكيف كانت استراتيجية "متعددة المناطق" (Multi-Region) هي طوق النجاة. سأشرح...

14 أبريل، 2026 قراءة المزيد
التوظيف وبناء الهوية التقنية

حسابي في GitHub كان مقبرة صامتة: كيف أنقذني ‘ملف التعريف المميّز’ من جحيم التجاهل؟

كنتُ أرى حسابي في GitHub كمقبرة لمشاريعي، مجرد أرشيف لا يلتفت إليه أحد. في هذه المقالة، سأشارككم قصتي، يا جماعة، كيف حوّلت هذا المستودع الصامت...

14 أبريل، 2026 قراءة المزيد
التوسع والأداء العالي والأحمال

عطل خدمة واحدة كاد ينسف النظام: كيف أنقذنا نمط “قاطع الدائرة” من جحيم الأعطال المتتالية؟

أشارككم قصة حقيقية من قلب المعركة التقنية، يوم كاد عطل في خدمة دفع صغيرة أن ينهار معه نظامنا بأكمله. سنغوص في تفاصيل نمط "قاطع الدائرة"...

14 أبريل، 2026 قراءة المزيد
البودكاست