Bloom Filters للمتوسط: افحص وجود مليون عنصر في 1.2MB ذاكرة
المستوى المطلوب: متوسط. الشرح بيفترض إنك مرتاح مع HashSet أو Dict في أي لغة، وتعرف الفرق بين O(1) و O(n) من غير ما نفسّرها من الصفر. لو لسه مبتدئ في الـ data structures، خد جولة في الـ HashSet الأول وارجع.
لو بتفحص "هل الـ user ده زار الصفحة قبل كده؟" على 80 مليون سجل في DB، أنت بتدفع 12ms لكل query. Bloom Filter بيرد على نفس السؤال في 0.4 microsecond، بـ 1.2MB ذاكرة بدل 6.4GB، بشرط واحد بسيط هتفهمه دلوقتي.
المشكلة باختصار
عندك سيرفر بيستقبل 12,000 طلب/ثانية، كل طلب لازم يتأكد إن user ID موجود في قائمة "المحظورين" (4 مليون ID). الحل المباشر: query على PostgreSQL. النتيجة: 12ms × 12,000 = استهلاك CPU 144 ثانية/ثانية. السيرفر بيختنق وانت لسه ما بدأتش الشغل الفعلي.
تحط القائمة كلها في Redis SET؟ يعمل، بس بياخد 320MB RAM. لو القائمة كبرت لـ 80 مليون، تبقى 6.4GB، وكل query بياخد قفزة شبكة (network hop) إضافية. Bloom Filter بيحل المشكلة دي بـ 1.2MB ثابتة في process memory نفسه، صفر شبكة، صفر I/O.
المثال البسيط للمبتدئ: بوّاب الحفلة
تخيّل بوّاب حفلة عنده ورقة فيها 4,000 اسم. كل ضيف بيوصل، البوّاب لازم يتأكد إن اسمه على القائمة. لو هيبحث خطّي اسم باسم، الضيف رقم 3,999 بياخد 4 ثواني والطابور بيقف.
الحل الذكي: البوّاب يحسب لكل اسم 3 أرقام (مجموع حروف، طول الاسم، كود حرف أول × 7). الـ 3 أرقام دي بتأشّر على 3 خانات في جدول 1,000 خانة. أول ما اسمك يدخل القائمة، الـ 3 خانات بتاعتك بتتعلّم عليها علامة.
لما ضيف جديد يوصل، البوّاب يحسب نفس الـ 3 أرقام، يبص للـ 3 خانات. لو واحدة منهم فاضية → الاسم مستحيل يكون على القائمة. لو الـ 3 كلها معلّمة → فيه احتمال كبير الاسم موجود، مع نسبة "إنذار كاذب" صغيرة محسوبة سلفًا.
ده Bloom Filter بالظبط: bit array + hash functions متعددة + ضمان رياضي إن "مش موجود" دائمًا صح.
التعريف العلمي الدقيق
Bloom Filter اخترعه Burton Howard Bloom سنة 1970 في ورقة منشورة في Communications of the ACM. هو data structure احتمالي مكوّن من:
- Bit array طوله m من البتات، بيبدأ كله أصفار.
- k hash functions مستقلة، كل واحدة بتاخد العنصر وترجّع رقم بين 0 و m-1.
عند الإضافة (insert): تحسب الـ k hashes للعنصر، تخلّي الـ k bits المقابلة = 1.
عند الفحص (query): تحسب الـ k hashes، تشوف الـ k bits. لو واحدة منهم 0 → العنصر قطعًا غير موجود. لو كلهم 1 → العنصر محتمل موجود (ممكن يكون false positive).
الميزة اللي محتاج تركّز فيها: false negatives مستحيلة رياضيًا. لو الـ filter قال "مش موجود" يبقى مش موجود حتمًا. الـ false positives بس هي اللي ممكنة، واحتمالها محسوب بالمعادلة دي: