Spring Boot умеет работать с Redis «из коробки» — достаточно добавить зависимость, указать адрес и выбрать нужный инструмент: ручные операции через RedisTemplate, автоматический кэш через @Cacheable или хранение сессий через Spring Session.
Подключение и клиент Lettuce
По умолчанию Spring Data Redis использует клиент Lettuce — асинхронный, потокобезопасный, основанный на Netty. Добавляем зависимость:
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
Настройка в application.yml:
spring:
data:
redis:
host: localhost
port: 6379
# password: secret # если включена аутентификация
# database: 0 # номер логической базы (0 по умолчанию)
lettuce:
pool:
max-active: 8
max-idle: 4
Spring Boot автоматически создаёт LettuceConnectionFactory и RedisTemplate<String, Object>. Переопределять бин подключения нужно только при нестандартной конфигурации (кластер, Sentinel, TLS).
RedisTemplate и StringRedisTemplate
RedisTemplate — универсальный инструмент для прямых операций с Redis. Он предоставляет «операции» по типу структуры данных:
@Service
public class CounterService {
private final StringRedisTemplate redis;
public CounterService(StringRedisTemplate redis) {
this.redis = redis;
}
public void increment(String key) {
redis.opsForValue().increment(key);
redis.expire(key, Duration.ofHours(1));
}
public Long get(String key) {
String value = redis.opsForValue().get(key);
return value != null ? Long.parseLong(value) : 0L;
}
}
StringRedisTemplate — это RedisTemplate<String, String> со строковой сериализацией. Подходит, когда и ключ, и значение — строки.
Операции по типу структуры:
| Метод | Тип данных Redis |
|---|---|
opsForValue() | String (скалярное значение) |
opsForHash() | Hash |
opsForList() | List |
opsForSet() | Set |
opsForZSet() | Sorted Set |
Грабля: сериализация по умолчанию
Если использовать RedisTemplate<String, Object> без настройки, значения сохраняются через JdkSerializationRedisSerializer. Данные в Redis выглядят как нечитаемый байтовый поток и привязаны к конкретным Java-классам — при изменении класса десериализация сломается.
Правильный подход — настроить JSON-сериализацию:
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
ObjectMapper mapper = new ObjectMapper();
mapper.activateDefaultTyping(
mapper.getPolymorphicTypeValidator(),
ObjectMapper.DefaultTyping.NON_FINAL
);
Jackson2JsonRedisSerializer<Object> serializer =
new Jackson2JsonRedisSerializer<>(mapper, Object.class);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(serializer);
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(serializer);
return template;
}
}
После этого значения в Redis хранятся как читаемый JSON.
Spring Cache поверх Redis
Spring Cache — абстракция над кэшем. Декорируешь метод аннотацией, Spring сам решает: сходить ли в базу или вернуть закэшированный результат.
Зависимость и включение
implementation 'org.springframework.boot:spring-boot-starter-cache'
@SpringBootApplication
@EnableCaching
public class Application { ... }
@Cacheable, @CacheEvict, @CachePut
@Service
public class ProductService {
@Cacheable(value = "products", key = "#id")
public Product findById(Long id) {
// вызывается только при отсутствии в кэше
return repository.findById(id).orElseThrow();
}
@CacheEvict(value = "products", key = "#product.id")
public void update(Product product) {
repository.save(product);
// кэш для этого ключа сбрасывается
}
@CachePut(value = "products", key = "#result.id")
public Product create(Product product) {
return repository.save(product);
// метод всегда выполняется, результат записывается в кэш
}
@CacheEvict(value = "products", allEntries = true)
public void invalidateAll() {
// удалить весь кэш products
}
}
RedisCacheManager и TTL
По умолчанию кэш живёт бесконечно. Задать TTL можно через RedisCacheManager:
@Configuration
public class CacheConfig {
@Bean
public RedisCacheManager cacheManager(RedisConnectionFactory factory) {
RedisCacheConfiguration defaults = RedisCacheConfiguration
.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(30))
.serializeValuesWith(
RedisSerializationContext.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer())
);
Map<String, RedisCacheConfiguration> cacheConfigs = Map.of(
"products", defaults.entryTtl(Duration.ofHours(1)),
"sessions", defaults.entryTtl(Duration.ofMinutes(5))
);
return RedisCacheManager.builder(factory)
.cacheDefaults(defaults)
.withInitialCacheConfigurations(cacheConfigs)
.build();
}
}
Короткая формула: RedisCacheConfiguration — это настройка одного кэша; RedisCacheManager собирает их вместе и регистрирует в Spring.
Сессии через Spring Session
Spring Session переносит пользовательские HTTP-сессии из памяти приложения в Redis. Это даёт две вещи:
- Горизонтальное масштабирование — несколько экземпляров приложения работают с общим хранилищем сессий, пользователь не теряет сессию при переключении между ними.
- Переживание перезапуска — сессии не исчезают при рестарте приложения.
Зависимость:
implementation 'org.springframework.session:spring-session-data-redis'
В application.yml:
spring:
session:
store-type: redis
timeout: 30m
redis:
flush-mode: on-save # записывать сессию только при изменении
namespace: "myapp:session"
Больше ничего настраивать не нужно — Spring Boot автоматически создаёт RedisIndexedSessionRepository и подключает фильтр SessionRepositoryFilter. Существующий код с HttpSession работает без изменений.
Как это выглядит в Redis
После запуска приложения с @Cacheable и Spring Session ключи в Redis будут выглядеть примерно так:
# Кэш через @Cacheable
> KEYS products::*
1) "products::42"
2) "products::17"
> GET "products::42"
"{\"id\":42,\"name\":\"Widget\",\"price\":9.99}"
> TTL "products::42"
(integer) 3542 # секунд до истечения
# Сессии через Spring Session
> KEYS myapp:session:*
1) "myapp:session:sessions:a3f9c..."
2) "myapp:session:sessions:b12ef..."
Коротко
- Lettuce — клиент по умолчанию в Spring Boot; потокобезопасный, настраивается в
application.yml. StringRedisTemplate— для строковых операций;RedisTemplate<String, Object>— для сложных значений.- Сериализацию менять обязательно: заменяй
JdkSerializationRedisSerializerнаGenericJackson2JsonRedisSerializer. @Cacheable/@CacheEvict/@CachePut— декларативный кэш;@EnableCachingвключает механизм.RedisCacheManagerнастраивает TTL отдельно для каждого кэша.- Spring Session переносит HTTP-сессии в Redis — масштабирование без потери сессий.
Что почитать дальше
- Основы Redis — структуры данных, TTL, персистентность
- Паттерны кэширования — cache-aside, read-through, write-through, когда что применять
- Эксплуатация Redis — мониторинг, репликация, Sentinel