Я новичок в Redis, возможно, это простой вопрос.
Я использую аннотации @Cacheable() и @CacheEvict(). Когда пользователь обновляется, и если я получаю пользователя по идентификатору, он извлекает кэшированные (устаревшие) данные. Конечно, если бы я использовал @CacheEvict(), этого бы не произошло.
Однако меня смущает @CacheEvict(), потому что результаты такие же, как если бы я его не использовал - так какой смысл его использовать? Если есть процесс, завершение которого занимает 3 секунды, то использование CacheEvict() также займет 3 секунды.
Вот мой класс UserServiceImpl.java:
package com.example.demo.serviceImpl;
import lombok.AllArgsConstructor;
import com.example.demo.model.User;
import com.example.demo.repository.UserRepository;
import com.example.demo.service.UserService;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
@Service
@EnableCaching
@AllArgsConstructor
public class UserServiceImpl implements UserService {
private UserRepository userRepository;
@Override
public User createUser(User user) {
return userRepository.save(user);
}
@Override
@CacheEvict(value = "users")
public User findUser(String userId) {
doLongRunningTask();
return userRepository.findById(userId).orElseThrow();
}
@Override
@Cacheable(value = "users")
public List findAll() {
return (List) userRepository.findAll();
}
@Override
@CacheEvict(value = "users", key = "#user.id")
public User updateUser(String userId, User user) {
doLongRunningTask();
user.setUpdatedAt(LocalDateTime.now());
return userRepository.save(user);
}
@Override
@CacheEvict(value = "users", key = "#userId")
public void deleteUser(String userId) {
userRepository.deleteById(userId);
}
private void doLongRunningTask() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Мой класс RedisConfig.java:
package com.example.demo.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import java.time.Duration;
import static org.springframework.data.redis.serializer.RedisSerializationContext.SerializationPair.fromSerializer;
@Configuration
public class RedisConfig {
@Value("${redis.host}")
private String redisHost;
@Value("${redis.port}")
private int redisPort;
@Bean
public LettuceConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
configuration.setHostName(redisHost);
configuration.setPort(redisPort);
return new LettuceConnectionFactory(configuration);
}
@Bean
public RedisCacheManager cacheManager() {
RedisCacheConfiguration cacheConfig = myDefaultCacheConfig(Duration.ofMinutes(10)).disableCachingNullValues();
return RedisCacheManager
.builder(redisConnectionFactory())
.cacheDefaults(cacheConfig)
.withCacheConfiguration("users", myDefaultCacheConfig(Duration.ofMinutes(5)))
.build();
}
private RedisCacheConfiguration myDefaultCacheConfig(Duration duration) {
return RedisCacheConfiguration
.defaultCacheConfig()
.entryTtl(duration)
.serializeValuesWith(fromSerializer(new GenericJackson2JsonRedisSerializer()));
}
}
Первое получение данных занимает 3 секунды. Получение тех же данных в следующий раз займет 5 мс (на этот раз они извлекаются из Redis, а не из postgres). Однако обновление этого пользователя и его повторная выборка дают устаревшие данные вместо вновь обновленного пользователя, что приводит к несогласованности данных.
ОБНОВЛЕНИЕ: это моя модель/пользователь. класс модели java
package com.example.demo.model;
import lombok.*;
import org.springframework.data.annotation.Id;
import org.springframework.data.redis.core.RedisHash;
@Data
@Builder
@RedisHash("user")
public class User {
@Id
private String id;
private String name;
private Integer age;
}
У меня также есть dto/UserDTO.java для преобразования модели в ответ/запрос REST через API:
package com.example.demo.dto;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserDTO implements Serializable {
@JsonProperty(value = "id")
private String id;
@JsonProperty(value = "name")
private String name;
@JsonProperty(value = "age")
private Integer age;
}
Благодаря @Max Kozlov этот класс DTO теперь является сериализуемым, поэтому Redis Cache может работать правильно.
Новый RedisCacheConfig. java благодаря ответу @Max Kozlov выглядит так:
package com.example.demo.config;
import com.example.demo.handler.DefaultCacheErrorHandler;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.CachingConfigurer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.CacheErrorHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import java.time.Duration;
@Configuration
@EnableCaching
public class RedisCacheConfig implements CachingConfigurer {
@Value("${redis.host}")
private String redisHost;
@Value("${redis.port}")
private int redisPort;
@Bean
public LettuceConnectionFactory redisConnectionFactory() {
RedisStandaloneConfiguration configuration = new RedisStandaloneConfiguration();
configuration.setHostName(redisHost);
configuration.setPort(redisPort);
return new LettuceConnectionFactory(configuration);
}
@Bean
public RedisCacheConfiguration redisCacheConfiguration() {
return RedisCacheConfiguration
.defaultCacheConfig()
.entryTtl(Duration.ofMinutes(15));
}
@Bean
@Override
public CacheErrorHandler errorHandler() {
return new DefaultCacheErrorHandler();
}
@Bean("longLifeCacheManager")
public CacheManager longLifeCacheManager() {
RedisCacheConfiguration defaultConfiguration = RedisCacheConfiguration
.defaultCacheConfig()
.entryTtl(Duration.ofDays(90));
return RedisCacheManager
.RedisCacheManagerBuilder
.fromConnectionFactory(redisConnectionFactory())
.cacheDefaults(defaultConfiguration)
.build();
}
@Primary
@Bean("shortLifeCacheManager")
public CacheManager shortLifeCacheManager() {
RedisCacheConfiguration defaultConfiguration = RedisCacheConfiguration
.defaultCacheConfig()
.entryTtl(Duration.ofDays(1));
return RedisCacheManager
.RedisCacheManagerBuilder
.fromConnectionFactory(redisConnectionFactory())
.cacheDefaults(defaultConfiguration)
.build();
}
}
Подробнее здесь: https://stackoverflow.com/questions/766 ... an-fetch-f
Java Spring Boot Redis – Как узнать, когда объект обновляется, чтобы я мог получить данные из базы данных вместо Redis? ⇐ JAVA
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Как получить все ключи из кэша Redis через Spring Boot с помощью Spring Data Redis 2.x?
Anonymous » » в форуме JAVA - 0 Ответы
- 27 Просмотры
-
Последнее сообщение Anonymous
-
-
-
Аутентификация NOAUTH требуется Spring-Boot-Data-Redis+Sealrease Latuce+Redis sentinel
Anonymous » » в форуме JAVA - 0 Ответы
- 15 Просмотры
-
Последнее сообщение Anonymous
-