Caffeine

Introducción

Cafeína es un alto rendimiento caching biblioteca para Java.

Una diferencia fundamental entre un cache y un Mapa es que un cache desaloja elementos almacenados.

Una política de desalojo decide qué objetos deben ser eliminados en un momento dado. Esta política afecta directamente al cache la tasa de éxito de — una característica crucial de caching bibliotecas.

Caffeine utiliza la política de desalojo Window TinyLfu, que proporciona una tasa de aciertos casi óptima.

Caffeine Configuración

Primero, vamos a crear un Caffeine bean. Esta es la configuración principal que controlará caching comportamiento como la expiración,cache límites de tamaño, y más:

    private CaffeineCache buildCaffeineCache(String name, CaffeineCacheSetting cacheSpec) {
        log.info("Cache {} specified timeout of {} min, max of {}", name, cacheSpec.getTimeout(), cacheSpec.getMaxSize());
        final Caffeine<Object, Object> caffeineBuilder =
            Caffeine.newBuilder()
                .expireAfterWrite(cacheSpec.getTimeout())
                .maximumSize(cacheSpec.getMaxSize())
                .recordStats();
        return new CaffeineCache(name, caffeineBuilder.build());
    }

A continuación, necesitamos otro bean utilizando el Spring CacheManager interfaz. Caffeine proporciona su implementación de esta interfaz, que requiere el Caffeine objeto que creamos arriba:

    @Bean(name = "ipfCacheManager")
    CacheManager ipfCaffeineCacheManager() {
        SimpleCacheManager manager = new SimpleCacheManager();
        if (Objects.nonNull(settings)) {
            List<CaffeineCache> caches = settings.entrySet().stream()
                .map(entry -> buildCaffeineCache(entry.getKey(), entry.getValue()))
                .collect(Collectors.toList());
            manager.setCaches(caches);
        }
        return manager;
    }

Todo el beans mencionado anteriormente lo obtenemos gratis al agregar el maven dependency mencionado anteriormente.

Sin embargo, el Caffeine cache requiere los siguientes valores de configuración para cada cache que se proporciona:

ipf.caching.caffeine.settings."${cache_name}".timeout=[Duration]
ipf.caching.caffeine.settings."${cache_name}".max-size=[Long]
  • cache_name-nombre del cache siendo utilizado

  • tiempo de espera-duración cache permanecerá en la memoria activa antes de ser desalojado.

  • max-size-máximo cache tamaño antes del cache desaloja entradas que son menos propensas a ser utilizadas nuevamente consulte Cafeína

Un ejemplo:

ipf.caching.caffeine.settings.cache1.timeout=10m
ipf.caching.caffeine.settings.cache1.max-size=10000
ipf.caching.caffeine.settings.cache2.timeout=20s
ipf.caching.caffeine.settings.cache2.max-size=100000

Caffeine Implementación

La implementación es sencilla, ya que este módulo es spring boot consciente de que conectará todo lo necesario beans y conéctelos a Spring CacheManager proporcionando métricas.

Solo agregue el maven dependency y luego recupere cualquier caches por nombre.

Obtenemos el CacheFactory*bean gratis de *ipf-cache-caffeine módulo y habilitando caffeine caching.

    @Bean(name = "caffeineCacheFactory")
    CacheFactory<?, ?> cacheFactory(CacheManager cacheManager, CacheLogger<Object, Object> cacheLogger) {
        return new CaffeineCacheFactory(cacheManager, cacheLogger);
    }

Entonces, solo necesita utilizar el CacheFactory para crear ya sea un AsyncCacheAdapter

        @Bean
        AsyncCacheAdapter<String, String> asyncCacheAdapter3(CacheFactory<String, String> cacheFactory) {
            return cacheFactory.asyncCreateCacheAdapter(CACHE_3);
        }

Or a CacheAdapter:

        @Bean
        CacheAdapter<?, ?> cacheAdapter1(CacheFactory<?, ?> cacheFactory) {
            return cacheFactory.createCacheAdapter(CACHE_1);
        }

Dependencias

La dependencia de ipf-cache-api el módulo requiere algunas dependencias suministradas para leer y escribir en el message log.

Estos pueden ser añadidos a su aplicación (si no están presentes) de la siguiente manera:

        @Bean
        ObjectMapper objectMapper() {
            return new ObjectMapper();
        }

        @Bean
        MessageLogger messageLogger() {
            return messageLogEntry -> log.info("log entry: {}", messageLogEntry);
        }