Skip to content

Instantly share code, notes, and snippets.

@jordisilvazup
Last active March 1, 2023 20:52
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jordisilvazup/2ac70a22f0644ed2c73ce5aeee2a7feb to your computer and use it in GitHub Desktop.
Save jordisilvazup/2ac70a22f0644ed2c73ce5aeee2a7feb to your computer and use it in GitHub Desktop.
Principais aprendizados para caching com Spring Data Redis

Spring Cache

Por si as anotações não provem um mecânismo de cache, isto signfica que os dados serão armazenados em memoria atraves de um ConcurrentHashMap. sem limitação de crescimento e sem politica de invalidação, e determinação de tempo de vida para objetos, oque pode gerar um alto uso de memoria e levar o aplicativo a morte.

Spring Cache oferece uma abstração para cachear chamada de metodos java. Isto signfica que independente se seu metodo faz grande esforço de CPU ou I/O o resultado poderá ser cacheado.

Spring Cache oferece suporte para configuração de diversos mecânismo de cache, como HazelCache, Cafeine, ECache e Redis.

Anotation

  1. @Cachable: Oferece a possibilidade de cachear o resultado de um metodo, quando um metodo anotado, recebe uma chamada é feito uma verificação se o resultado já existe no cache, caso não exista o metodo é executadoi e seu retorno é cacheado para execuções posteriores. Caso o resultado para determinada entrada exista em cache, este valor é retornado e o metodo anotado não é executado.

Por padrão o primeiro argumento de um metodo é utilizado como chave de chace, como é defino no SimpleKeyGenerator.class Caso o metodo contenha mais de um parâmetro, é possivel determinar qual argumento será utilizado como chave através da propriedade Key, que deve ser definida atraves de SpEL (Spring Expresion Language).

Também é possivel definir condições para o cacheamento, através do argumento condition.

  1. @CachePut: Deve ser utilizada para realizar a atualização do cache. Ao contrario de @Cachable a anotação @CachePut faz com que o metodo sempre seja invocado, e seu resultado é armazenado em cache. Esta anotação deve ser utilizado quando é necessário atualizar o cache sem interferir na execução do metodo. Também aceita as opções determinadas em @Cachable.

  2. @CacheEvict É a abstração que deve ser utilizada em metodos que são gatilhos para invalidação do cache. Por padrão ira invalidar o cache da chave determinada através da entrada do metodo, caso seja necessário invalidar todas as chaves, o argumento allEntries=true. A invalidação do cache acontece por padrão após a execução do metodo, pois caso alguma Exceção seja lançada e interropa a execução do mesmo, o cache não será invalidado. Caso o seja necessário invalidar o cache independente da execução do metodo, o argumento beforeInvocation=true deverá ser utilizado.

Spring Cache com Spring Data Redis

  • Necessário a definição que o Redis sera utilizado como provedor de cache, e deve ser feito atraves da propertie cache.type=redis

  • Ao utilizar o Spring Cache com Redis, o cache é feito de forma 100% distribuida, isto significa que as politicas de invalidação serão feitas através do client redis Java. Spring Data Redis utiliza por padrão o Lettuce Client, que não suporta a definição de cache no client, isto significa que os objetos não cacheados localmente em memoria, então não é possível determinar um tamanho maximo para o cache. O que pode ser feito é definição do tempo de vida para o objeto (TTL).

  • Por padrão a serialização dos objetos é feita através de JdkSerializationRedisSerializer, que é conhecido pela execução de codigo remoto, o que pode prejudicar a segurança do aplicativo, pois se torna vulneravel a injeção de bytecode não verificado. Spring Data Redis recomenda que utilize outro formato para Serialização como Json que é suportado pelo Spring através do GenericJackson2JsonRedisSerializer. A alteração deve ser feita de maneira programatica.

  • Definição de TTL: por padrão o RedisCacheManager é construido com uma unica configuração para todos Caches, isto significa que se necessário a configuração de diferentes cache, deve ser feita de maneira programatica.

@Configuration
@EnableCaching
public class RedisConfig {
     @Bean
    public RedisCacheConfiguration defaultCacheConfiguration() {
        return RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofMinutes(120)) //define default time to live
                .disableCachingNullValues()
                .serializeValuesWith(fromSerializer(new GenericJackson2JsonRedisSerializer())); // define default serializer
    }
}
  • Estaticas do Cache: por padrão é desligada, então não é possível analizar e exportar metricas de cada caching. Para habilitar é necessário redefinir a construção do RedisCacheManager de formar programatica.
@Configuration
@EnableCaching
public class RedisConfig {
    @Bean
    public RedisCacheManager redisCacheManager(RedisConnectionFactory connectionFactory) {
        return RedisCacheManager.builder(connectionFactory)
                .enableStatistics()
                .build();

    }
}
  • Habilitando o Logging
logging:
    level:
        org.springframework.cache: TRACE

Referências

  1. Spring Data Redis
  2. Spring Cache 3.2, aqui fornece mais detalhes que a versão atual
  3. Spring Cache atual
  4. Customizer TTL Redis Cache
  5. Spring Cache With Redis: Baeldung
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment