فلتر بلوم (Bloom Filter): كيف أنقذنا خوادمنا من جحيم فحص قواعد البيانات الضخمة؟

يا هلا فيكم يا جماعة، معكم أخوكم أبو عمر.

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

المستخدم الجديد يدخل اسم مستخدم (username) وبريد إلكتروني، ونحن بدورنا لازم نتأكد إذا هالمعلومات مستخدمة من قبل أو لأ. العملية بسيطة منطقياً: استعلام `SELECT` على جدول المستخدمين اللي فيه عشرات الملايين من السجلات. في البداية، كان الأمر يأخذ أجزاء من الثانية. بعدين صار ياخذ ثانية… ثانيتين… ومع الضغط العالي، كانت قاعدة البيانات “بتشكي وبتولول” من كثرة استعلامات الفحص هاي. صار فريق البنية التحتية كل يوم يبعت لنا تقارير عن استهلاك الـ CPU العالي على سيرفر قاعدة البيانات، والسبب الأكبر هو استعلامات التحقق من وجود المستخدمين.

في ليلة من ليالي الدعم الفني الطويلة، وأنا بشرب فنجان القهوة الثالث وبحاول ألاقي حل، خطرت ببالي محاضرة حضرتها في الجامعة عن “هياكل البيانات الاحتمالية” (Probabilistic Data Structures). وقتها كان كلام نظري، لكن اليوم… اليوم كان ممكن يكون طوق النجاة. تذكرت اسم غريب: “فلتر بلوم”. قلت للشباب: “يا جماعة، شو رأيكم نجرب إشي مجنون شوي؟”.

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

ما هو “فلتر بلوم” (Bloom Filter) يا أبو عمر؟

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

لاحظوا إني حكيت “قد يكون” وما حكيت “موجود بالتأكيد”. وهون كل السحر. فلتر بلوم مثل حارس أمن على باب حفلة كبيرة معه قائمة المدعوين، لكن ذاكرته مش 100%. لما ييجي شخص، الحارس بيسأله عن اسمه وبيشيك على ذاكرته:

  • إذا الحارس حكى: “اسمك مش موجود عندي، تفضل اطلع بره”، فهو صادق 100%. لو كان اسمك على القائمة، كان رح يتذكر.
  • إذا الحارس حكى: “أهلاً وسهلاً، اسمك مألوف، تفضل ادخل”، فهو قد يكون صادقاً، أو قد يكون مخطئاً وتشابه عليه اسمك مع اسم شخص آخر.

هذا يعني أن فلتر بلوم عنده خاصيتين ذهبيتين:

  1. لا يوجد نتائج سلبية كاذبة (No False Negatives): إذا قال لك الفلتر إن العنصر “غير موجود”، فهو حتماً غير موجود.
  2. قد يوجد نتائج إيجابية كاذبة (Can have False Positives): إذا قال لك الفلتر إن العنصر “موجود”، فهو غالباً موجود، لكن هناك احتمال ضئيل أنه مخطئ.

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

كيف يعمل هذا السحر؟ (الآلية التقنية)

فلتر بلوم قائم على فكرتين أساسيتين: مصفوفة من البتات (Bit Array) ومجموعة من دوال التجزئة (Hash Functions).

لنفترض أن لدينا مصفوفة من 18 خانة (bit)، كلها أصفار في البداية، ولدينا 3 دوال تجزئة مختلفة (k=3).


[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]

1. إضافة عنصر جديد (مثل “abu_omar”)

لما بدنا نضيف عنصر جديد، بنمرره على دوال التجزئة الثلاثة. كل دالة بتعطينا رقم (مؤشر) داخل المصفوفة. خلينا نفترض النتائج كانت هيك:

  • hash1("abu_omar") -> 2
  • hash2("abu_omar") -> 9
  • hash3("abu_omar") -> 14

الآن، بنروح على المصفوفة وبنحوّل الخانات رقم 2, 9, 14 إلى 1.


[0,0,1,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0]

وهيك بنكون “سجلنا” وجود “abu_omar” في الفلتر.

2. التحقق من وجود عنصر (مثل “salem”)

الآن، لنفترض أن مستخدم جديد يريد التسجيل باسم “salem”. هل هو موجود؟ بنعمل نفس العملية:

  • hash1("salem") -> 5
  • hash2("salem") -> 12
  • hash3("salem") -> 17

بنروح نتفحص الخانات 5, 12, 17 في المصفوفة. بنلاقي إن الخانة رقم 5 قيمتها 0. بما أننا وجدنا صفر واحد على الأقل، فهذا يعني بالتأكيد أن “salem” لم تتم إضافته من قبل. بنجاوب “غير موجود” ونحن متأكدون 100%.

3. التحقق من عنصر موجود (أو إيجابي كاذب)

ماذا لو تحققنا من “abu_omar” مرة أخرى؟ سنحصل على نفس المؤشرات (2, 9, 14)، وسنجد أن كل الخانات المقابلة لها قيمتها 1. هنا نقول: “هذا العنصر قد يكون موجوداً”.

طيب وين الإيجابي الكاذب (False Positive)؟
لنفترض أننا أضفنا “fatima” و “yousef” للفلتر، وتغيرت قيم أخرى في المصفوفة إلى 1. الآن جاء مستخدم جديد اسمه “khaled”. بالصدفة البحتة، قد تكون نتائج دوال التجزئة لـ “khaled” تشير إلى خانات تم تحويلها إلى 1 بسبب “abu_omar” و “fatima” و “yousef”. مثلاً:

  • hash1("khaled") -> 9 (تم تحويله بواسطة “abu_omar”)
  • hash2("khaled") -> 4 (تم تحويله بواسطة “fatima”)
  • hash3("khaled") -> 11 (تم تحويله بواسطة “yousef”)

عند التحقق من “khaled”، سيجد الفلتر أن كل الخانات (9, 4, 11) قيمتها 1، وسيقول “إنه قد يكون موجوداً”، مع أننا لم نضف “khaled” أبداً! هذا هو الإيجابي الكاذب. في هذه الحالة، سنذهب إلى قاعدة البيانات لنكتشف الحقيقة ونجد أنه غير موجود فعلاً.

الجميل في الموضوع أننا نستطيع التحكم في نسبة حدوث هذه الأخطاء عبر زيادة حجم المصفوفة وعدد دوال التجزئة.

مثال عملي: لنكتب الكود معًا!

الحكي النظري حلو، بس خلينا نشوف كود حقيقي. ما في داعي نخترع العجلة، هناك مكتبات ممتازة جاهزة للاستخدام. في بايثون، واحدة من أشهرها هي pybloom-live.

لنفترض أننا نريد بناء فلتر بلوم لفحص وجود البريد الإلكتروني في نظامنا الذي نتوقع أن يصل إلى 5 ملايين مستخدم، ونريد نسبة خطأ لا تتجاوز 0.1%.


# أولاً، قم بتثبيت المكتبة
# pip install pybloom-live

from pybloom_live import BloomFilter
import time

# 1. تهيئة فلتر بلوم
# ===================
# سنقوم بإنشاء فلتر يتسع لـ 5 مليون عنصر
# مع نسبة خطأ إيجابي كاذب (false positive) لا تتجاوز 0.1% (0.001)
# المكتبة ستقوم بحساب حجم المصفوفة وعدد دوال التجزئة الأنسب تلقائياً
capacity = 5000000
error_rate = 0.001

print("جاري إنشاء فلتر بلوم...")
# يمكن حفظ الفلتر في ملف وإعادة تحميله لاحقاً
# user_emails_filter = BloomFilter(capacity=capacity, error_rate=error_rate, filepath='emails.bloom')
user_emails_filter = BloomFilter(capacity=capacity, error_rate=error_rate)
print("تم إنشاء الفلتر بنجاح!")
print(f"حجم الفلتر: {user_emails_filter.num_bits / 8 / 1024 / 1024:.2f} MB")
print(f"عدد دوال التجزئة: {user_emails_filter.num_hashes}")


# 2. إضافة بعض البيانات (محاكاة إضافة مستخدمين)
# ================================================
print("nجاري إضافة مليون بريد إلكتروني للفلتر...")
start_time = time.time()
for i in range(1000000):
    email = f"user{i}@example.com"
    user_emails_filter.add(email)
end_time = time.time()
print(f"تمت إضافة مليون بريد في {end_time - start_time:.2f} ثانية.")

# لنضف بريداً إلكترونياً نعرفه
user_emails_filter.add("abu_omar@my-company.com")


# 3. مرحلة التحقق (هنا يظهر السحر)
# =================================
print("n--- مرحلة التحقق ---")

# الحالة الأولى: بريد إلكتروني غير موجود بالتأكيد
email_to_check_1 = "a_brand_new_user@example.com"
if email_to_check_1 in user_emails_filter:
    # هذه الحالة نادرة الحدوث (تعتمد على نسبة الخطأ)
    print(f"'{email_to_check_1}': الفلتر يقول 'قد يكون موجوداً'. يجب التحقق من قاعدة البيانات.")
else:
    # هذه هي الحالة الأغلب للعناصر الجديدة
    print(f"'{email_to_check_1}': الفلتر يقول 'غير موجود بالتأكيد'. ✅ يمكن تسجيله مباشرة دون فحص قاعدة البيانات.")

# الحالة الثانية: بريد إلكتروني موجود بالفعل
email_to_check_2 = "abu_omar@my-company.com"
if email_to_check_2 in user_emails_filter:
    print(f"'{email_to_check_2}': الفلتر يقول 'قد يكون موجوداً'. يجب التحقق من قاعدة البيانات. (وهو موجود فعلاً)")
else:
    # هذا الفرع من الكود مستحيل أن يتم تنفيذه
    print(f"'{email_to_check_2}': مستحيل! حدث خطأ ما.")

# الحالة الثالثة: إيجابي كاذب (False Positive) - نادر الحدوث
# هذا البريد لم نضفه، لكن قد يخبرنا الفلتر أنه موجود بالصدفة
email_to_check_3 = "some_random_unseen_email@domain.com"
if email_to_check_3 in user_emails_filter:
    print(f"'{email_to_check_3}': الفلتر يقول 'قد يكون موجوداً'. 😱 هذا مثال على الإيجابي الكاذب. سنتحقق من قاعدة البيانات لنكتشف أنه غير موجود.")
else:
    print(f"'{email_to_check_3}': الفلتر يقول 'غير موجود بالتأكيد'.")

لاحظوا كيف أننا في الحالة الأولى، وفرنا استعلاماً كاملاً عن قاعدة البيانات. لو كان لديك 1000 طلب تسجيل في الثانية، و 99% منهم أسماء جديدة، فأنت قد وفرت 990 استعلاماً في الثانية! هذا هو الفرق بين نظام ينهار ونظام يعمل بكفاءة.

نصائح أبو عمر الذهبية لاستخدام فلاتر بلوم

من خبرتي في الميدان، هذه بعض النصائح العملية:

  1. متى تستخدمه؟ استخدمه كـ “طبقة أولى” من الفحص قبل الوصول لمصدر بيانات مكلف (قاعدة بيانات، API خارجي، نظام ملفات ضخم). مثالي لـ:
    • فحص توفر اسم المستخدم/البريد الإلكتروني.
    • منع عرض محتوى مكرر للمستخدم (مقالات، منتجات).
    • إنشاء قائمة سوداء (Blacklist) لعناوين IP أو نطاقات خبيثة.
    • تقليل الاستعلامات في أنظمة التخزين المؤقت (Caching).
  2. متى لا تستخدمه؟ لا تستخدمه أبداً إذا كانت نتيجة “الإيجابي الكاذب” كارثية. مثلاً، لا تستخدمه وحده لتحديد إذا كان مريض قد أخذ جرعة دواء قاتلة. أيضاً، تذكر أن فلتر بلوم التقليدي لا يدعم الحذف. إذا حذفت مستخدماً من قاعدة البيانات، لا يمكنك إزالته بسهولة من الفلتر.
  3. كيف تتعامل مع عدم القدرة على الحذف؟ هناك حلول. أبسطها هو إعادة بناء الفلتر بشكل دوري (مثلاً كل ليلة). الحل الأكثر تقدماً هو استخدام نسخة معدلة تسمى “فلتر بلوم العدّاد” (Counting Bloom Filter) الذي يسمح بالحذف، لكنه يستهلك مساحة أكبر.
  4. اختر أبعادك بحكمة: قبل بناء الفلتر، يجب أن يكون لديك تقدير جيد لعدد العناصر التي ستخزنها (Capacity) ومقدار الخطأ الذي يمكنك تحمله (Error Rate). لا تخمن! استخدم الآلات الحاسبة المتوفرة على الإنترنت أو دع المكتبة التي تستخدمها تحسب لك الأبعاد المثلى. كلما قلت نسبة الخطأ، زادت المساحة التي يحتاجها الفلتر.

الخلاصة: الحارس الذكي لقاعدة بياناتك

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

بفضل هذا “الحارس”، استطعنا في مشروعنا تخفيض الحمل على قاعدة البيانات بنسبة تزيد عن 80%، وحولنا نظاماً على حافة الانهيار إلى نظام سريع ومستجيب. كل هذا مقابل بضعة ميغابايتات في الذاكرة وخوارزمية بسيطة.

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

ويا هلا فيكم مرة ثانية!

أبو عمر

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

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

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

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

آخر المدونات

الحوسبة السحابية

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

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

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

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

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

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

كان عطلٌ واحدٌ يُسقط النظام بأكمله: كيف أنقذنا ‘نمط قاطع الدائرة’ من جحيم الانهيارات المتسلسلة؟

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

1 يونيو، 2026 قراءة المزيد
التكنلوجيا المالية Fintech

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

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

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