Caching en Kotlin: Redis, Memcached y soluciones integradas — de la A a la Z
El caching es una de las herramientas clave para mejorar el rendimiento de las aplicaciones. En el ecosistema de Kotlin, que funciona sobre JVM y Android, el desarrollador tiene a su disposición múltiples soluciones: desde sistemas distribuidos (Redis, Memcached) hasta cachés locales integrados (Caffeine, Guava Cache, Ehcache). En este artículo, analizaremos cómo integrar cada uno de ellos en un proyecto Kotlin, proporcionaremos ejemplos de código y daremos recomendaciones para su elección.
1. Caching integrado en JVM: Caffeine y Guava Cache
Para el caching local en Kotlin, la mejor opción es Caffeine, una biblioteca de alto rendimiento escrita en Java y totalmente compatible con Kotlin. Admite la expulsión automática por tiempo, por tamaño y basada en pesos. Una alternativa es Guava Cache de Google, pero Caffeine es más rápido (a menudo de 2 a 3 veces).
Ejemplo: Caffeine + Kotlin
Añada la dependencia en build.gradle.kts:
implementation("com.github.ben-manes.caffeine:caffeine:3.1.8")Creamos un caché de 1000 elementos con TTL de 10 minutos:
import com.github.benmanes.caffeine.cache.Caffeineimport java.util.concurrent.TimeUnit
val cache = Caffeine.newBuilder() .maximumSize(1000) .expireAfterWrite(10, TimeUnit.MINUTES) .build<String, String>()
// Usocache.put("user:42", "{\\"name\\":\\"Alice\\"}")val user = cache.getIfPresent("user:42")println(user) // {"name":"Alice"}Ejemplo: Guava Cache + Kotlin
implementation("com.google.guava:guava:33.0.0-jre")import com.google.common.cache.CacheBuilderimport java.util.concurrent.TimeUnit
val guavaCache = CacheBuilder.newBuilder() .maximumSize(500) .expireAfterWrite(5, TimeUnit.MINUTES) .build<String, String>()
guavaCache.put("session:abc", "active")println(guavaCache.getIfPresent("session:abc")) // activeCuándo usarlo: para almacenar datos temporales de una sola instancia de la aplicación (por ejemplo, resultados de cálculos complejos, tokens, configuraciones). No es adecuado para microservicios con múltiples instancias: los datos no se sincronizan.
2. Redis — caching distribuido para microservicios
Redis es un almacén en memoria de tipo clave-valor que se utiliza como caché distribuido, broker de mensajes y base de datos. Para Kotlin, el mejor cliente es Lettuce (asíncrono, reactivo, thread-safe).
Instalación y conexión
implementation("io.lettuce:lettuce-core:6.3.2.RELEASE")Ejemplo: conexión y operaciones básicas
import io.lettuce.core.RedisClientimport io.lettuce.core.api.sync.RedisCommands
val client = RedisClient.create("redis://localhost:6379")val connection = client.connect()val commands: RedisCommands<String, String> = connection.sync()
// Establecemos una clave con TTL de 60 segundoscommands.setex("user:123", 60, "{\\"name\\":\\"Bob\\"}")
// Leemosval data = commands.get("user:123")println(data) // {"name":"Bob"}
connection.close()client.shutdown()Ejemplo: cliente reactivo (Kotlin Coroutines)
import io.lettuce.core.RedisClientimport io.lettuce.core.api.reactive.RedisReactiveCommandsimport kotlinx.coroutines.reactive.awaitFirstOrNull
suspend fun getFromRedis(key: String): String? { val client = RedisClient.create("redis://localhost:6379") val connection = client.connect() val reactive: RedisReactiveCommands<String, String> = connection.reactive()
val result = reactive.get(key).awaitFirstOrNull() connection.close() client.shutdown() return result}Cuándo usarlo: sistemas distribuidos, microservicios, sesiones compartidas, rate limiting, pu