Interview - Comment déterminer rapidement si un élément est dans un ensemble ?

Comment déterminer rapidement si un élément est dans un ensemble ? Ce sujet est une question que je pose souvent lors d'entretiens récents, et différentes personnes ont de nombreuses réponses différentes à cette question.

Aujourd'hui, je veux présenter une solution que peu de gens mentionneront, c'est-à-dire avec l'aide du filtre Bloom.

1. Qu'est-ce qu'un filtre Bloom ?

Le filtre Bloom a été proposé par un frère nommé Bloom en 1970.

En fait, il peut être considéré comme une structure de données constituée d'un vecteur binaire (ou tableau de bits) et d'une série de fonctions de mappage aléatoires (fonctions de hachage).

Son avantage est que l'efficacité de l'espace et le temps de requête sont bien meilleurs que l'algorithme général, et l'inconvénient est qu'il a un certain taux de fausse reconnaissance et qu'il est difficile à supprimer.

image

2. Principe de mise en œuvre

Venez avec une image

image

 L'idée principale de l'algorithme de filtre Bloom est d'utiliser n fonctions de hachage pour le hachage afin d'obtenir différentes valeurs de hachage, de les mapper à différentes positions d'index du tableau (la longueur de ce tableau peut être très longue) en fonction du hachage, et puis définissez la valeur du bit d'index correspondant sur 1.

Pour juger si l'élément apparaît dans l'ensemble, il s'agit d'utiliser k fonctions de hachage différentes pour calculer la valeur de hachage, et voir si la valeur au-dessus de la position d'index correspondante de la valeur de hachage est 1. S'il y en a une qui n'est pas 1, cela signifie que l'élément n'existe pas dans la collection.

Mais il est aussi possible de juger que l'élément est dans l'ensemble, mais l'élément ne l'est pas, le 1 surtout les positions d'index de cet élément est fixé par d'autres éléments, ce qui conduit à une certaine probabilité d'erreur de jugement (c'est pourquoi le ci- dessus peut vivre dans un ensemble) La cause première, car il y aura un certain conflit de hachage).

Remarque : Plus le taux de faux positifs est faible, plus les performances correspondantes sont faibles.

3. Fonction

Les filtres Bloom peuvent être utilisés pour déterminer si un élément est ( probablement ) dans un ensemble, et par rapport à d'autres structures de données, les filtres Bloom ont d'énormes avantages dans l'espace et le temps.

Notez le mot ci-dessus : éventuellement. Il reste un suspense ici, qui sera analysé en détail ci-dessous.

  • Déterminer si les données fournies existent

  • Empêcher la pénétration du cache (juger si les données demandées sont efficaces pour éviter de contourner directement la base de données de demande de cache), etc., filtrage anti-spam des boîtes aux lettres, fonctions de liste noire, etc.

4. Réalisation concrète

Après avoir lu l'idée de l'algorithme du filtre Bloom, commencez l'explication de l'implémentation spécifique.

Permettez-moi d'abord de donner un exemple. Supposons qu'il y ait deux chaînes, Wangcai et Xiaoqiang. Elles passent par l'algorithme de hachage trois fois respectivement, puis définissent la valeur de la position d'index du tableau correspondant (en supposant que la longueur du tableau est de 16) à 1 selon le résultat du hachage. , regardez d'abord l'expression "richesse de prospérité" :

image

Une fois que Wangjing a haché trois fois, les valeurs sont respectivement 2, 4 et 6. Ensuite, les valeurs d'index peuvent être obtenues sous la forme 2, 4 et 6, respectivement, de sorte que la valeur de l'index (2, 4 , 6) du tableau est mis à 1. Le reste est considéré comme 0. Supposons maintenant que vous ayez besoin de rechercher une richesse prospère. Après les trois mêmes hachages, on constate que les valeurs des positions correspondant aux indices 2 , 4 et 6 sont tous 1, on peut donc juger qu'une richesse prospère peut exister.

Insérez ensuite Xiaoqiang dans le filtre Bloom, le processus réel est le même que ci-dessus, en supposant que les indices obtenus sont 1, 3, 5

image

Mis à part l'existence de Wangcai, Xiaoqiang est comme ceci dans le filtre Bloom à ce moment, et le tableau réel combinant Wangcai et Xiaoqiang est comme ceci :

image

 Maintenant, il y a une donnée : 9527. Maintenant, l'exigence est de juger si 9527 existe. Supposons que les indices obtenus par 9527 après trois hachages sont : 5, 6 et 7. Il s'avère que la valeur de la position avec l'indice 7 est 0, alors on peut déterminer avec certitude que 9527 ne doit pas exister.

Puis vint un  007 domestique . Après trois hachages, les indices obtenus sont : 2, 3 et 5. Il s'avère que les valeurs correspondant aux indices 2, 3 et 5 sont toutes à 1, donc on peut en juger grossièrement que le  007 domestique peut exister. . Mais en fait, après notre démonstration tout à l'heure, le domestique 007 n'existe pas du tout. La raison pour laquelle la valeur des positions d'index 2, 3 et 5 est de 1 est que d'autres données sont définies.

En parlant de ça, je ne sais pas si tout le monde comprend le rôle du filtre Bloom.

image

 5. Mise en œuvre du code

En tant que programmeurs Java, nous sommes vraiment heureux. Nous utilisons beaucoup de frameworks et d'outils, et ils sont essentiellement encapsulés. Pour les filtres Bloom, nous utilisons des classes d'outils encapsulées par Google. Bien sûr, il existe d'autres moyens que vous pouvez explorer.

Ajoutez d'abord les dépendances

<!--布隆过滤依赖-->
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>25.1-jre</version>
</dependency>

Implémentation du code

import com.google.common.hash.BloomFilter;
import com.google.common.hash.Funnels;
import java.nio.charset.Charset;

public class BloomFilterDemo {
    
    public static void main(String[] args) {
        /**
         * 创建一个插入对象为一亿,误报率为0.01%的布隆过滤器
         * 不存在一定不存在
         * 存在不一定存在
         * ----------------
         *  Funnel 对象:预估的元素个数,误判率
         *  mightContain :方法判断元素是否存在
         */
        BloomFilter<CharSequence> bloomFilter = BloomFilter.create(Funnels.stringFunnel(Charset.forName("utf-8")), 100000000, 0.0001);
        bloomFilter.put("死");
        bloomFilter.put("磕");
        bloomFilter.put("Redis");
        System.out.println(bloomFilter.mightContain("Redis"));
        System.out.println(bloomFilter.mightContain("Java"));
    }
}

 Des explications précises ont été écrites dans les commentaires. À ce stade, je pense que tout le monde doit comprendre le filtre Bloom et comment l'utiliser.

6. Combat réel

Simulons un scénario où la pénétration du cache est résolue par un filtre bloom.

Tout d'abord, savez-vous ce qu'est la pénétration du cache ?

La pénétration du cache signifie que les utilisateurs accèdent à des données qui ne se trouvent ni dans le cache ni dans la base de données. Étant donné que le cache n'existe pas, ils accéderont à la base de données si la simultanéité est élevée. Il est facile de submerger la base de données

Comment le filtre Bloom résout-il ce problème ? il

Le principe est le suivant : placez toutes les conditions de requête dans la base de données dans le filtre bloom, lorsqu'une requête de requête arrive, elle sera d'abord vérifiée via le filtre bloom, et s'il est jugé que la valeur de requête demandée existe, elle continuera à check ; S'il est jugé que la requête demandée n'existe pas, elle sera directement rejetée.

Son code est le suivant :

String get(String key) {
    String value = redis.get(key);     
    if (value  == null) {
        if(!bloomfilter.mightContain(key)){
            return null; 
        }else{
            value = db.get(key); 
            redis.set(key, value); 
        }    
    }
    return value;
}

7. Résumé

Cet article détaille qu'est-ce qu'un filtre bloom ? quel est l'effet? Le principe d'implémentation et le filtre Bloom sont expliqués à partir de nombreux aspects du niveau de code. J'espère pouvoir contribuer à vos progrès d'apprentissage.

Je suppose que tu aimes

Origine blog.csdn.net/qq_34272760/article/details/121198811
conseillé
Classement