Java Spring Boot Redis – Как узнать, когда объект обновляется, чтобы я мог получить данные из базы данных вместо Redis?JAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Java Spring Boot Redis – Как узнать, когда объект обновляется, чтобы я мог получить данные из базы данных вместо Redis?

Сообщение Anonymous »

Я новичок в 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
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «JAVA»