2017-04-18 5 views
0

Je veux supprimer quelques entrées de cache si la clé dans le cache correspond à un motif.La meilleure façon de supprimer l'entrée de cache en fonction du prédicat dans infinispan?

Par exemple, j'ai la paire valeur clé suivante dans le cache,

("key-1", "value-1"), ("key-2", "value-2"), ("key-3", "value-3"), ("key-4", "value-4") 

Depuis cache implémente une interface cartographique, je peux le faire comme ça

cache.entrySet().removeIf(entry -> entry.getKey().indexOf("key-") > 0); 

Y at-il une meilleure façon de le faire dans infinispan (peut-être en utilisant fonctionnelle ou cache api flux)?

Répondre

2

La méthode removeIf sur entrySet devrait fonctionner correctement. Il sera cependant plutôt lent pour un cache distribué, car il attirera toutes les entrées du cache et évaluera le prédicat localement, puis effectuera une suppression pour chaque entrée correspondante. Même dans un cache répliqué, il doit toujours effectuer tous les appels de suppression (au moins, l'itérateur sera local). Cette méthode peut être modifiée dans le futur car nous mettons déjà à jour les méthodes Map [a].

Une autre option consiste à utiliser à la place l'API fonctionnelle comme vous l'avez dit [1]. Malheureusement, la façon dont cela est mis en œuvre est de tirer toutes les entrées localement en premier. Cela peut être modifié ultérieurement si les API de cartes fonctionnelles deviennent plus populaires. Un autre choix est l'API de flux de cache qui peut être un peu plus encombrant à utiliser, mais qui vous fournira les meilleures performances de toutes les options. Heureux que vous l'ayez mentionné :) Ce que je recommanderais est d'appliquer d'abord toutes les opérations intermédiaires (heureusement dans votre cas vous pouvez utiliser le filtre puisque vos clés ne changeront pas simultanément). Utilisez ensuite l'opération de terminal forEach qui passe le cache sur ce nœud [2] (notez qu'il s'agit d'un remplacement). A l'intérieur du callable forEach, vous pouvez appeler la commande remove comme vous le souhaitez.

cache.entrySet().parallelStream() // stream() if you want single thread per node 
    .filter(e -> e.getKey().indexOf("key-") > 0) 
    .forEach((cache, e) -> cache.remove(e.getKey())); 

Vous pouvez également utiliser l'indexation pour éviter l'itération du conteneur aussi bien, mais je ne vais pas entrer dans ce ici. L'indexation est une bête complètement différente.

[a] https://issues.jboss.org/browse/ISPN-5728

[1] https://docs.jboss.org/infinispan/9.0/apidocs/org/infinispan/commons/api/functional/FunctionalMap.ReadWriteMap.html#evalAll-java.util.function.Function-

[2] https://docs.jboss.org/infinispan/9.0/apidocs/org/infinispan/CacheStream.html#forEach-org.infinispan.util.function.SerializableBiConsumer-

+0

Merci pour la réponse précieuse, je ne pouvais pas faire la api readwritemap fonctionnelle pour supprimer quelques entrées en fonction evalMany. Mais votre solution basée sur api de flux de cache résout mon problème. – Sriram