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

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

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

Начать курс

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

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

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

Кэш позволяет сократить время ответа приложения за счёт хранения часто запрашиваемых данных в быстродоступной памяти. Это особенно актуально для:

  • высоконагруженных REST API;
  • работы с внешними API и базами данных;
  • ресурсоёмких вычислений;
  • сессионных данных пользователей.

Основные стратегии кэширования

Прежде чем выбирать библиотеку, важно понимать базовые стратегии:

  • Cache-Aside — приложение само управляет кэшем: сначала проверяет кэш, при промахе загружает данные из БД и помещает их в кэш.
  • Read-Through — кэш автоматически загружает данные из источника при промахе.
  • Write-Through / Write-Behind — запись данных одновременно (или асинхронно) в кэш и в основное хранилище.

1. Redis из Kotlin

Redis — это in-memory key-value хранилище, которое часто используется как распределённый кэш. Для работы с Redis в Kotlin используется клиент Lettuce (асинхронный, реактивный) или Jedis (синхронный).

Подключение Lettuce

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

Пример работы с Redis через Lettuce (Kotlin)

import io.lettuce.core.RedisClient
import io.lettuce.core.api.coroutines

suspend fun main() {
    val client = RedisClient.create("redis://localhost:6379")
    val connection = client.connect()
    val commands = connection.coroutines() // корутинный API

    // Запись
    commands.setex("user:123:profile", 3600, "{\"name\":\"Alice\"}")
    
    // Чтение
    val cached = commands.get("user:123:profile")
    println("Из кэша: $cached")
    
    connection.close()
    client.shutdown()
}

Когда использовать Redis?

  • Нужен распределённый кэш между несколькими экземплярами приложения.
  • Требуется высокая отказоустойчивость и репликация.
  • Данные должны быть доступны после перезапуска приложения (персистентность Redis).
  • Необходима поддержка сложных структур (списки, множества, очереди).

2. Caffeine — высокопроизводительный локальный кэш

Caffeine — это библиотека для in-memory кэширования на JVM, написанная на Java. Она часто используется в связке со Spring Boot, но отлично работает и в чистом Kotlin. Caffeine обеспечивает почти нулевую задержку при чтении.

Подключение Caffeine

// build.gradle.kts
implementation("com.github.ben-manes.caffeine:caffeine:3.1.8")

Пример использования Caffeine в Kotlin

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

data class User(val id: Int, val name: String)

fun createCache(): Caffeine<Int, User>.() -> Unit = {
    maximumSize(10_000)
    expireAfterWrite(10, TimeUnit.MINUTES)
    recordStats()
}

val userCache = Caffeine.newBuilder()
    .maximumSize(10_000)
    .expireAfterWrite(10, TimeUnit.MINUTES)
    .build<Int, User>()

fun getUserFromCache(id: Int): User? {
    return userCache.getIfPresent(id)
}

fun putUser(id: Int, user: User) {
    userCache.put(id, user)
}

// Пример с автоматической загрузкой (LoadingCache)
val loadingCache = Caffeine.newBuilder()
    .maximumSize(5_000)
    .build<Int, User> { id ->
        // эмуляция загрузки из БД
        User(id, "User_$id")
    }

Когда использовать Caffeine?

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