Page cover

Data Structure 1: Bloom Filter

Struktur Data Bloom Filter: Pengertian, Cara Kerja, dan Implementasi dalam Go

Pendahuluan

Dalam pemrosesan data, seringkali kita perlu melakukan dua operasi penting:

  1. Membership Query: Memeriksa apakah suatu data d ada dalam kumpulan data S.

  2. Insertion: Menambahkan d ke S tanpa duplikasi.

Solusi naif menggunakan array atau hash table bisa tidak efisien karena membutuhkan memori besar. Bloom Filter hadir sebagai struktur data probabilitas yang menyeimbangkan penggunaan memori dan kecepatan, meski dengan toleransi false positive.


Konsep Dasar

1. Bit Array

Awalnya, data direpresentasikan dengan bit array. Misal, himpunan {0, 1, 4} direpresentasikan sebagai:

0 | 1 | 2 | 3 | 4 | 5 | 6 | 7  
-----------------------------  
1 | 1 | 0 | 0 | 1 | 0 | 0 | 0  

Setiap data di-hash ke posisi bit tertentu. Namun, ukuran array harus sebesar jumlah data, sehingga tidak efisien.

2. Fungsi Hash

Untuk menghemat memori, digunakan fungsi hash h(x) yang memetakan data ke indeks dalam array yang lebih kecil. Misal, h(x) = x mod 8.

Masalah: Tabrakan (collision) terjadi ketika dua data berbeda di-hash ke indeks yang sama. Ini mengurangi akurasi dan memperlambat pencarian.


Bloom Filter: Solusi Probabilistik

Bloom Filter mengatasi masalah tabrakan dengan menggunakan beberapa fungsi hash sekaligus. Setiap data di-hash oleh k fungsi hash, dan setiap hasil hash menentukan posisi bit yang akan diset ke 1.

Contoh:

  • Data "hello" di-hash ke posisi 9, 4, 1.

  • Data "alice" di-hash ke posisi 8, 1, 2.

Bit array setelah penyisipan:

Pengecekan Keanggotaan:

  • Jika semua bit pada posisi hash suatu data bernilai 1, data mungkin ada di himpunan (bisa false positive).

  • Jika ada bit yang 0, data pasti tidak ada (no false negative).


Implementasi dalam Bahasa Go

1. Struktur Data

2. Fungsi Hash

Menggunakan kombinasi hash FNV-1a dengan indeks sebagai parameter:

3. Operasi Tambah dan Cek

4. Contoh Penggunaan


Karakteristik Bloom Filter

  1. False Positive vs. False Negative

    • False Positive: Data tidak ada tapi dikatakan ada (bisa terjadi).

    • False Negative: Data ada tapi dikatakan tidak ada (tidak mungkin).

  2. Kompleksitas

    • Ruang: O(m), dengan m = ukuran bit array.

    • Waktu: O(k), dengan k = jumlah fungsi hash.

  3. Parameter Optimal Untuk meminimalkan false positive:

    • Ukuran array: m = -(n ln p)/(ln 2)^2

    • Jumlah hash: k = (m/n) ln 2 Dimana n = jumlah data, p = probabilitas false positive.


Aplikasi di Dunia Nyata

Use Case Real-World untuk Bloom Filter

1. Validasi Username yang Sudah Terdaftar

  • Masalah: Mengecek ketersediaan username secara real-time tanpa query database berulang.

  • Solusi:

    • Simpan semua username terdaftar dalam Bloom Filter.

    • Saat registrasi, cek Bloom Filter:

      • Jika false, username pasti belum terdaftar.

      • Jika true, lakukan pengecekan ulang ke database.

2. Pendeteksian URL Berbahaya

  • Masalah: Browser perlu memblokir URL phishing/malware dengan cepat.

  • Solusi:

    • Simpan daftar URL berbahaya di Bloom Filter.

    • Saat pengguna mengakses URL, cek Bloom Filter:

      • Jika true, tampilkan peringatan atau lakukan verifikasi lebih lanjut.

3. Cache Layer untuk Database

  • Masalah: Query database untuk data yang tidak ada menghabiskan sumber daya.

  • Solusi:

    • Simpan record yang sudah dihapus di Bloom Filter.

    • Sebelum query database, cek Bloom Filter:

      • Jika true, lewati query (data sudah dihapus).


Best Practice Implementasi

Aspek
Rekomendasi

Ukuran Array (m)

Gunakan rumus m = -(n * ln(p)) / (ln(2)^2) untuk meminimalkan false positive.

Jumlah Hash (k)

Optimal: k = (m/n) * ln(2). Mulai dengan 3-5 hash.

Penyimpanan

Simpan bit array di memory (Redis/Memcached) untuk akses cepat.

Persistence

Backup berkala ke disk/database.

Monitoring

Hitung false positive rate dan sesuaikan parameter.


Masih belum dapat intuisi nya? Saya akan coba terangkan sekali lagi ya🥰


Alur dan Simulasi Bloom Filter

1. Inisialisasi

Bloom Filter diinisialisasi dengan:

  • Bit Array: Array berisi 0 atau 1 (direpresentasikan sebagai []bool di Go).

  • Fungsi Hash: Sejumlah k fungsi hash independen.

  • Ukuran Array (m): Jumlah bit dalam array.

Contoh: Membuat Bloom Filter dengan:

  • Ukuran array (m) = 10

  • Jumlah fungsi hash (k) = 3

Bit array awal:


2. Menambahkan Data

Setiap data di-hash oleh k fungsi hash untuk mendapatkan k posisi bit. Bit pada posisi tersebut diubah ke 1.

Contoh: Tambahkan data "apple":

  1. Hash "apple" dengan 3 fungsi hash:

    • h1("apple") → Posisi 1

    • h2("apple") → Posisi 4

    • h3("apple") → Posisi 7

  2. Set bit di posisi 1, 4, dan 7 ke 1:

Bit array setelah ditambahkan "apple":

Tambahkan data "banana":

  1. Hash "banana" dengan 3 fungsi hash:

    • h1("banana") → Posisi 3

    • h2("banana") → Posisi 4

    • h3("banana") → Posisi 9

  2. Set bit di posisi 3, 4, dan 9 ke 1:

Bit array setelah ditambahkan "banana":


3. Pemeriksaan Keanggotaan

Untuk memeriksa apakah suatu data ada:

  1. Hash data dengan k fungsi hash.

  2. Jika semua bit di posisi hash bernilai 1 → data mungkin ada.

  3. Jika ada bit yang 0 → data pasti tidak ada.

Contoh: Periksa "apple":

  1. Hash "apple" → Posisi 1, 4, 7.

  2. Bit di posisi 1, 4, 7 = 1.

  3. Hasil: True (mungkin ada).

Periksa "cherry":

  1. Hash "cherry" → Posisi 0, 2, 5.

  2. Bit di posisi 0, 2, 5 = 0.

  3. Hasil: False (pasti tidak ada).


4. Simulasi False Positive

Kasus: Periksa "grape":

  1. Hash "grape" → Posisi 1, 3, 9 (misal).

  2. Bit di posisi 1, 3, 9 = 1 (karena di-set oleh "apple" dan "banana").

  3. Hasil: True (padahal "grape" tidak pernah ditambahkan → false positive).

Bit array saat ini:


5. Ilustrasi Alur Lengkap

Ilustrasi

6. Parameter yang Mempengaruhi Akurasi

  1. Ukuran Array (m): Semakin besar m, semakin kecil kemungkinan false positive.

  2. Jumlah Fungsi Hash (k): Terlalu sedikit → collision meningkat. Terlalu banyak → bit array cepat penuh.

Rumus Optimal:

  • Ukuran array: ( m = -\frac{n \ln p}{(\ln 2)^2} )

  • Jumlah hash: ( k = \frac{m}{n} \ln 2 )

Di mana:

  • ( n ): Jumlah data yang akan disimpan.

  • ( p ): Toleransi probabilitas false positive.


Kesimpulan Simulasi

  • Bloom Filter tidak menyimpan data asli, hanya merepresentasikan keanggotaan data melalui bit array.

  • Tidak ada false negative: Jika hasilnya False, data pasti tidak ada.

  • Ada false positive: Jika hasilnya True, data mungkin ada atau tidak.

Contoh Koding Go

Berikut penjelasan implementasi Bloom Filter dalam skenario nyata, disertai contoh kode Go dan Docker Compose:

Implementasi di Go dengan Docker

1. Struktur Bloom Filter

2. REST API dengan Gin

3. Docker Compose


Cara Menjalankan

  1. Build dan jalankan dengan Docker:

  2. Contoh penggunaan API:


Optimasi untuk Production

  1. Gunakan Redis:

  2. Multiple Hash Libraries:

  3. Monitoring:

    • Hitung metrik:

      • bloom_false_positives_total

      • bloom_memory_usage_bytes


Implementasi ini cocok untuk sistem yang memprioritaskan kecepatan dan skalabilitas, seperti validasi real-time atau caching layer. Bloom Filter menjadi garda terdepan sebelum akses ke sumber daya yang lebih berat seperti database.

Kesimpulan

Bloom Filter menawarkan solusi efisien untuk masalah keanggotaan data dengan mengorbankan sedikit akurasi. Implementasinya yang sederhana dan penggunaan memori minimal membuatnya cocok untuk sistem yang memprioritaskan kecepatan dan skalabilitas. Namun, pengguna harus mempertimbangkan trade-off antara ukuran memori dan tingkat false positive.

Referensi:

https://loop-learn-share.netlify.app/data-structure/bloom_filter.html

Last updated