Подробное объяснение использования Caffeine LoadingCache

задняя часть

эффект

  1. тайник
  2. Асинхронно и непрерывно обновлять кеш

Создание объекта LoadingCache

LoadingCache<Integer, String> loadingCache = Caffeine.newBuilder()
                .expireAfterWrite(1, TimeUnit.SECONDS)
                .refreshAfterWrite(500, TimeUnit.MILLISECONDS)
                .maximumSize(10) // 缓存最大数量
                .removalListener((RemovalListener<Integer, String>) (integer, s, removalCause) -> {
                    System.out.println("key:" + integer + " value:" + s + " cause:"+removalCause);
                })
                .build(new CacheLoader<Integer, String>() {
                    @Nullable
                    @Override
                    public String load(@NonNull Integer i) throws Exception {
                        return i.toString();
                    }

                    @Override
                    public Map<Integer, String> loadAll(Iterable<? extends Integer> keys) {
                        Map<Integer, String> map = new HashMap<>();
                        for (Integer i : keys) {
                            map.put(i, i.toString());
                        }
                        return map;
                    }
                });

разбор параметров

  • expireAfterWrite: стратегия истечения срока действия, аналогичные параметры expireAfterAccess, ключ не будет удален сразу после истечения времени кэширования, кофеин использует стратегию ленивого удаления, изменяется в LoadingCache, например добавление, обновление и т. д., или ключ с истекшим сроком действия доступ будет удален.
  • refreshAfterWrite: стратегия обновления, установленная на время, меньшее, чем время записи, чтобы гарантировать, что кеш никогда не станет недействительным. В некоторых сценариях, таких как бизнес с низкой частотой запросов, но длительным временем, автоматическое обновление может значительно повысить эффективность и удобство.
  • maxSize: максимальное количество кэшированных элементов. Если оно превышает это число, кофеин удалит некоторые ключи в соответствии со стратегией Window TinyLfu. Аналогичные параметры также имеют максимальный вес. Пример кода выглядит следующим образом. Вес, если совокупный вес достигает максимального веса, ключ будет устранен.Стратегия устранения такая же, как и у maxSize, независимо от веса. Кроме того, maxSize и MaximumWeight нельзя использовать одновременно, иначе будет сообщено об исключении IllegalStateException.
LoadingCache<Integer, String> weightLoadingCache = Caffeine.newBuilder()
                .maximumWeight(1000)
                .weigher((Weigher<Integer, String>) (integer, s) -> integer)
                .build(new CacheLoader<Integer, String>() {
                    @Nullable
                    @Override
                    public String load(@NonNull Integer integer) throws Exception {
                        return null;
                    }
                });
  • removeListener: стратегия для выполнения при удалении кеша, например ведение журнала и т. д.
  • параметр сборки CacheLoader: стратегия, используемая для загрузки кеша во время обновления, в зависимости от конкретного бизнеса. Рекомендуется реализовать метод load All при реализации метода загрузки. Метод loadAll подходит для требований к кешу пакетных запросов или при обновлении cache включает сетевое взаимодействие и другие трудоемкие операции. Например, ваши кэшированные данные должны быть получены из Redis. Если loadAll не реализован, требуется несколько операций загрузки, что требует многократных взаимодействий Redis, что занимает очень много времени. Если loadAll реализован, вы можете отправить пакетный запрос на redis в loadAll., значительно сократив количество и время сетевых взаимодействий и значительно повысив эффективность.

Меры предосторожности

Caffeine не кэширует нулевые значения. Если при загрузке возвращается null, caffeine удалит соответствующий ключ из кэша. В то же время карта, возвращаемая loadAll, не может содержать данные, значение которых равно null, иначе будет сообщено об исключении NullPointerException.

Общий метод

V get(@NonNull K key)

Возвращает данные заданного ключа в LoadingCache. Если такого ключа в кеше нет, для загрузки данных будет вызван метод load CacheLoader. Если данные не могут быть загружены, будет возвращено значение null.

Map<K, V> getAll(@NonNull Iterable<? extends K> keys)

Возвращает кэшированные данные ключей в keys и объединяет их в карту. Если ключ или некоторые ключи не существуют в кеше, для загрузки данных будет вызван loadAll. Если loadAll по-прежнему не может загрузить ключ данных, он в обратку ставить не будут.в карте.

void refresh(@NonNull K key)

Чтобы явно обновить ключ, вызовите асинхронную загрузку.

ставить, ставитьВсе

Эти два метода явно добавляют кеш, для LoadingCache на самом деле нет необходимости его вызывать, потому что кеш будет автоматически загружен при get и getAll, если кеш не существует.

проблема

Хотя LoadingCache определяет refreshAfterWrite, на самом деле, если вы не обращаетесь к кешу, он не будет обновляться автоматически, то есть LoadingCache является ленивым обновлением.