Introducción: ¿Por qué es necesario el caché en Java?
\nEn el desarrollo moderno de alta carga, la velocidad de acceso a los datos es un factor crítico. Cada solicitud a la base de datos o a una API externa aumenta el tiempo de respuesta y la carga en la infraestructura. El caché en Java permite almacenar datos solicitados con frecuencia en memoria de alta velocidad (RAM), reduciendo el tiempo de respuesta de decenas de milisegundos a microsegundos.
\nEn este artículo, analizaremos tres enfoques principales para el almacenamiento en caché: soluciones integradas (HashMap, Caffeine, Ehcache), Redis y Memcached. Aprenderá cómo elegir la herramienta adecuada y verá ejemplos de código funcionales.
\n\n1. Soluciones integradas para caché en Java
\nPara proyectos pequeños o aplicaciones de un solo hilo, a menudo son suficientes las colecciones integradas. Sin embargo, para entornos de producción es mejor utilizar bibliotecas especializadas.
\n\n1.1. Caché simple con HashMap
\nLa forma más sencilla es usar ConcurrentHashMap con gestión manual del tiempo de vida. Es adecuado para prototipos, pero no tiene mecanismos de desalojo (eviction).
import java.util.concurrent.ConcurrentHashMap;\nimport java.util.concurrent.TimeUnit;\n\npublic class SimpleCache {\n private final ConcurrentHashMap<String, CacheEntry> cache = new ConcurrentHashMap<>();\n\n public void put(String key, Object value, long ttlMs) {\n cache.put(key, new CacheEntry(value, System.currentTimeMillis() + ttlMs));\n }\n\n public Object get(String key) {\n CacheEntry entry = cache.get(key);\n if (entry == null || System.currentTimeMillis() > entry.expiry) {\n cache.remove(key);\n return null;\n }\n return entry.value;\n }\n\n private record CacheEntry(Object value, long expiry) {}\n}\n\n1.2. Caffeine — caché de alto rendimiento para Java
\nCaffeine es una biblioteca moderna utilizada en Spring Cache. Admite desalojo automático por tiempo, tamaño y frecuencia de uso.
\nimport com.github.benmanes.caffeine.cache.Cache;\nimport com.github.benmanes.caffeine.cache.Caffeine;\nimport java.util.concurrent.TimeUnit;\n\npublic class CaffeineExample {\n public static void main(String[] args) {\n Cache<String, String> cache = Caffeine.newBuilder()\n .expireAfterWrite(10, TimeUnit.MINUTES)\n .maximumSize(1000)\n .build();\n\n cache.put("user_1", "Alexey");\n String user = cache.getIfPresent("user_1");\n System.out.println(user); // Alexey\n }\n}\n\n1.3. Ehcache — estándar empresarial
\nEhcache es una solución madura con soporte para agrupación en clústeres y persistencia en disco. Se usa a menudo junto con Hibernate.
\nimport org.ehcache.Cache;\nimport org.ehcache.CacheManager;\nimport org.ehcache.config.builders.CacheConfigurationBuilder;\nimport org.ehcache.config.builders.CacheManagerBuilder;\nimport org.ehcache.config.builders.ResourcePoolsBuilder;\n\npublic class EhcacheExample {\n public static void main(String[] args) {\n CacheManager cacheManager = CacheManagerBuilder.newCacheManagerBuilder()\n .withCache("users",\n CacheConfigurationBuilder.newCacheConfigurationBuilder(\n String.class, String.class,\n ResourcePoolsBuilder.heap(100))\n ).build();\n cacheManager.init();\n\n Cache<String, String> cache = cacheManager.getCache("users", String.class, String.class);\n cache.put("user_2", "Maria");\n System.out.println(cache.get("user_2")); // Maria\n\n cacheManager.close();\n }\n}\n\n2. Redis — caché distribuido para Java
\nRedis es un almacén de datos en memoria que funciona como un servidor separado