Cache em Java: Redis, Caffeine, Ehcache e JCache
Cache é uma das ferramentas-chave para melhorar o desempenho de aplicações Java. Ele permite reduzir o tempo de resposta, diminuir a carga em bancos de dados e APIs externas. Neste artigo, abordaremos três soluções populares: Redis (cache distribuído externo), Caffeine (cache in-memory de alto desempenho) e Ehcache (cache híbrido com suporte a disco). Também veremos o padrão JCache (JSR 107), que unifica o trabalho com caches.
Por que usar cache em Java?
Principais cenários de uso:
- Redução de latência — dados do cache são retornados em microssegundos, não em milissegundos (como em consultas ao banco de dados).
- Diminuição da carga — o cache protege o banco de dados de consultas repetitivas.
- Economia de recursos — menos chamadas a serviços externos → menos custos de infraestrutura.
1. Redis — cache distribuído para microsserviços
Redis é um armazenamento de dados in-memory frequentemente usado como cache distribuído. Ele suporta várias estruturas de dados: strings, hashes, listas, conjuntos. Para Java, existem dois clientes principais: Jedis e Lettuce (recomendado para Spring Boot).
Exemplo de conexão via Spring Data Redis:
@Configurationpublic class RedisConfig { @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) { RedisTemplate<String, Object> template = new RedisTemplate<>(); template.setConnectionFactory(connectionFactory); template.setKeySerializer(new StringRedisSerializer()); template.setValueSerializer(new GenericJackson2JsonRedisSerializer()); return template; }}
@Servicepublic class UserService { @Autowired private RedisTemplate<String, Object> redisTemplate;
public User getUserById(String id) { String key = "user:" + id; User cached = (User) redisTemplate.opsForValue().get(key); if (cached != null) return cached;
User user = database.findUserById(id); // consulta cara redisTemplate.opsForValue().set(key, user, 10, TimeUnit.MINUTES); return user; }}Vantagens do Redis: distribuído, suporte a TTL, pub/sub, persistência. Desvantagens: latência de rede, consumo de memória no servidor.
2. Caffeine — cache in-memory ultrarrápido
Caffeine é uma biblioteca para cache local baseada no algoritmo W-TinyLFU. Ela oferece quase 100% de hit rate com consumo mínimo de memória. Ideal para aplicações single-thread e multi-thread.
Exemplo de uso do Caffeine:
Cache<String, User> cache = Caffeine.newBuilder() .expireAfterWrite(5, TimeUnit.MINUTES) .maximumSize(10_000) .recordStats() .build();
public User getUser(String id) { return cache.get(id, key -> database.findUserById(key));}
// Obtendo estatísticasCacheStats stats = cache.stats();System.out.println("Hit rate: " + stats.hitRate());Vantagens do Caffeine: latência mínima (nanossegundos), estatísticas integradas, remoção automática de entradas antigas. Desvantagens: apenas cache local, não adequado para sistemas distribuídos.
3. Ehcache — cache híbrido com gravação em disco
Ehcache é uma das bibliotecas de cache mais antigas para Java. Suporta cache em memória e em disco, além de clusterização via Terracotta. Frequentemente usado em conjunto com Hibernate.
Exemplo de configuração do Ehcache 3 (XML):
<config xmlns:xsi="http://www.w3.org Também na biblioteca
Migrações de banco de dados em C# (.NET): Entity Framework, FluentMigrator e outras abordagens
protobuf para C++: guia completo com exemplos
tsyringe para TypeScript: guia completo com exemplos práticos
Prisma para JavaScript (Node.js): guia completo com exemplos