Лучший способ удалить запись в кеше на основе предиката в infinispan?

Я хочу удалить несколько записей в кеше, если ключ в кеше соответствует какому-то шаблону.

Например, у меня есть следующая пара ключ-значение в кеше:

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

Поскольку кеш реализует интерфейс карты, я могу сделать так

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

Есть ли лучший способ сделать это в infinispan (может быть, с использованием функционального или кеш-потока API)?


person Sri    schedule 18.04.2017    source источник


Ответы (1)


Метод removeIf для entrySet должен работать нормально. Однако для распределенного кеша это будет довольно медленно, поскольку он будет извлекать каждую запись в кеше и оценивать предикат локально, а затем выполнять удаление для каждой совпадающей записи. Даже в реплицированном кеше он все равно должен выполнять все вызовы удаления (по крайней мере, итератор будет локальным). Этот метод может быть изменен в будущем, так как мы уже обновляем методы карты [a].

Другой вариант — вместо этого использовать функциональный API, как вы сказали [1]. К сожалению, способ, которым это реализовано, заключается в том, что сначала все записи будут извлекаться локально. Это может быть изменено позже, если API функциональных карт станут более популярными.

Еще одним вариантом является API потока кэширования, который может быть немного более громоздким в использовании, но обеспечит вам наилучшую производительность из всех вариантов. Рад, что вы упомянули об этом :) Я бы порекомендовал сначала применить любые промежуточные операции (к счастью, в вашем случае вы можете использовать фильтр, поскольку ваши ключи не будут меняться одновременно). Затем используйте терминальную операцию forEach, которая передает кэш на этом узле [2] (обратите внимание, что это переопределение). Внутри вызываемого объекта forEach вы можете вызвать команду удаления так, как хотите.

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()));

Вы также можете использовать индексирование, чтобы избежать итерации контейнера, но я не буду вдаваться в подробности. Индексация — это совершенно другой зверь.

[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-

person Mudokonman    schedule 18.04.2017
comment
Спасибо за ценный ответ, я не смог заставить функциональный API readwritemap удалить несколько записей на основе evalMany. Но ваше решение на основе API потока кеша решает мою проблему. - person Sri; 19.04.2017