Кэширование в Kotlin: Redis, Caffeine и другие решения

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Кэширование в Kotlin: Redis, Caffeine и альтернативы

Кэширование — один из ключевых инструментов для повышения производительности приложений. В Kotlin, благодаря совместимости с Java и богатой экосистеме JVM, доступно множество решений: от легковесного in-memory кэша до распределённых систем на базе Redis. В этой статье разберём популярные библиотеки, их настройку и примеры использования.

Зачем нужно кэширование?

Основные цели кэширования:

  • Снижение времени ответа (latency) за счёт хранения часто запрашиваемых данных в быстрой памяти.
  • Уменьшение нагрузки на базы данных и внешние API.
  • Экономия вычислительных ресурсов при повторяющихся запросах.

Kotlin позволяет использовать как нативные Java-библиотеки, так и специализированные Kotlin-обёртки.

1. Redis через Lettuce или Redisson

Redis — самый популярный in-memory data store для распределённого кэширования. В Kotlin его подключают через клиенты Lettuce (реактивный) или Redisson (синхронный/асинхронный).

Пример: кэширование с Lettuce

// build.gradle.kts
implementation("io.lettuce:lettuce-core:6.3.1.RELEASE")

// CacheService.kt
import io.lettuce.core.RedisClient
import io.lettuce.core.api.sync.RedisCommands

class RedisCache(private val host: String = "localhost", private val port: Int = 6379) {
    private val client: RedisClient = RedisClient.create("redis://$host:$port")
    private val connection = client.connect()
    private val sync: RedisCommands<String, String> = connection.sync()

    fun get(key: String): String? = sync.get(key)
    fun set(key: String, value: String, ttlSeconds: Long = 60) {
        sync.setex(key, ttlSeconds, value)
    }
    fun delete(key: String) = sync.del(key)
    fun close() {
        connection.close()
        client.shutdown()
    }
}

// Использование
fun main() {
    val cache = RedisCache()
    cache.set("user:123", """{"name":"Alice","role":"admin"}""", 120)
    val data = cache.get("user:123")
    println(data) // {"name":"Alice","role":"admin"}
    cache.close()
}

Redisson — более высокоуровневый API

implementation("org.redisson:redisson:3.27.2")

val config = Config().apply {
    useSingleServer().setAddress("redis://127.0.0.1:6379")
}
val redisson = Redisson.create(config)
val map = redisson.getMap<String, String>("userCache")
map["user:456"] = """{"name":"Bob"}"""
val bob = map["user:456"]
redisson.shutdown()

2. Caffeine — быстрый in-memory кэш

Caffeine — современная замена Guava Cache. Оптимизирована для высоких нагрузок, поддерживает автоматическую выгрузку устаревших записей.

implementation("com.github.ben-manes.caffeine:caffeine:3.1.8")

import com.github.benmanes.caffeine.cache.Cache
import com.github.benmanes.caffeine.cache.Caffeine
import java.util.concurrent.TimeUnit

val cache: Cache<String, String> = Caffeine.newBuilder()
    .expireAfterWrite(10, TimeUnit.MINUTES)
    .maximumSize(10_000)
    .recordStats()
    .build()

// Запись и чтение
cache.put("key1", "value1")
val value = cache.getIfPresent("key1")
println(value) // value1

// Статистика
val stats = cache.stats()
println("Hit rate: ${stats.hitRate()}")

3. Hazelcast — распределённый кэш с кластеризацией

Hazelcast подходит для микросервисных архитектур: кэш автоматически синхронизируется между узлами.

implementation("com.hazelcast:hazelcast:5.3.6")

import com.hazelcast.core.Hazelcast
import com.hazelcast.map.IMap

val instance = Hazelcast.newHazelcastInstance()
val map: IMap<String, String> = instance.getMap("session-cache")
map.put("session:token123", "userId=42", 30, TimeUnit.MINUTES)
val userId = map.get("session:token123")
instance.shutdown()

4. Spring Cache с Kotlin

Если вы используете Spring Boot, подключение кэша становится тривиальным. Поддерживаются Redis, Caffeine, Hazelcast и другие.

// build.gradle.kts
implementation("org.springframework.boot:spring-boot-starter-cache")
implementation("org.springframework.boot:spring-boot-starter-data-redis")

// application.yml
spring:
  cache:
    type: redis
  redis:
    host: localhost
    port: 6379

// Сервис
@Service
class UserService(private val userRepository: UserRepository) {
    @Cacheable("users")
    fun getUser(id: Long): User {
        Thread.sleep(2000) // имитация медленного зап                    

Рекомендаций