Redis의 RedisTemplate
, @Cacheable
, @CacheEvict
개념을 정리해봅니다.
0) Redis 설치및 run
https://velog.io/@mooh2jj/Redis-설치 참고
1) dependency & propertire
// redis
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
// https://mvnrepository.com/artifact/redis.clients/jedis
implementation group: 'redis.clients', name: 'jedis', version: '3.3.0'
spring:
redis:
host: localhost
port: 6379 # redis 기본포트 6379
redisTemplate를 통해 더 다양한 자료구조를 사용할 수도 있다.
@RestController
@RequiredArgsConstructor
public class RedisTestController {
private final StringRedisTemplate redisTemplate;
@GetMapping("/setFruit")
public String setFruit(@RequestParam String name) {
ValueOperations<String, String> ops = redisTemplate.opsForValue();
ops.set("fruit", name);
return "saved";
}
@GetMapping("/getFruit")
public String getFruit() {
ValueOperations<String, String> ops = redisTemplate.opsForValue();
return ops.get("fruit");
}
}
이외에도 자료구조에 따라 타입이 다른 메소드들이 있다.
1) @EnableCaching
: @Cacheable이라는 어노테이션이 명시된 메서드가 실행될 때 내부적으로 Proxy, AspectJ 기반 어드바이스를 CacheInterceptor 와 연결하여 Spring에서 캐시 관리에 필요한 구성요소로 등록됨.
@EnableCaching
@SpringBootApplication
public class FestaApplication {
public static void main(String[] args) {
SpringApplication.run(FestaApplication.class, args);
}
}
2) RedisCacheKey
public class RedisCacheKey {
public static final String STUDY_GROUP_LIST = "studyGroupList_userId";
public static final String RESERVATION_LIST = "reservationList_roomId";
}
3) RedisConfig
@Configuration
public class RedisConfig {
@Value("${spring.redis.host}")
private String redisHost;
@Value("${spring.redis.port}")
private int redisPort;
// Creating Connection with Redis
@Bean
public RedisConnectionFactory redisConnectionFactory() {
return new LettuceConnectionFactory(new RedisStandaloneConfiguration(redisHost, redisPort));
}
// Creating RedisTemplate for Entity 'Reservation'
// StringRedisSerializer: binary 데이터로 저장되기 때문에 이를 String 으로 변환시켜주며(반대로도 가능) UTF-8 인코딩 방식을 사용
// GenericJackson2JsonRedisSerializer: 객체를 json 타입으로 직렬화/역직렬화를 수행
@Bean
public RedisTemplate<String, Object> redisTemplate(){
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory());
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return redisTemplate;
}
/**
* Redis Cache 설정
* Map을 이용하여 캐시 키를 등록
* 모든 키에 대한 설정이 아닌 각각의 키 별로 지정할 수 있게 STUDYGROUP_LIST 키 하나에 한정해서 180초로 설정
*/
@Bean
public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory) {
RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig()
.serializeKeysWith(RedisSerializationContext
.SerializationPair
.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext
.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer()));
Map<String, RedisCacheConfiguration> cacheConfigurationMap = new HashMap<>();
// entryTtl 설정
cacheConfigurationMap.put(RedisCacheKey.STUDYGROUP_LIST,
redisCacheConfiguration.entryTtl(Duration.ofSeconds(180L)));
return RedisCacheManager
.RedisCacheManagerBuilder
.fromConnectionFactory(redisConnectionFactory)
.cacheDefaults(redisCacheConfiguration)
.build();
}
}
4) entryTtl 설정
여기서 entryTtl
을 알아보자. TTL
은 cache 만료시간
을 뜻한다.
시간타입을, second, Day 등 바꿀 수도 있다.
// entryTtl 설정
cacheConfigurationMap.put(RedisCacheKey.STUDYGROUP_LIST,
redisCacheConfiguration.entryTtl(Duration.ofSeconds(180L)));
1) @Cacheable
: 데이터를 조회할 때, 레디스 캐싱 처리
@Cacheable(key = "#studyGroupId" ,value = STUDYGROUP_LIST, cacheManager = "redisCacheManager")
@Transactional(readOnly = true)
@Override
public StudyGroupResponse getById(Long studyGroupId) {
StudyGroup studyGroup = studyGroupRepository.findById(studyGroupId)
.orElseThrow(() -> {
log.error("studyGroup 대상이 없습니다. studyGroupId: {}", studyGroupId);
throw new WSApiException(ErrorCode.NO_FOUND_ENTITY, "can't find a StudyGroup by " +
" studyGroupId: " + studyGroupId);
});
return mapToDto(studyGroup);
}
2) @CacheEvict
: value or cacheNames 으로 지정된 레디스 캐시 제거, 캐시 키 값은 @CacheEvict 로 지워주지 않는 한, 메모리에 계속 남아있게 된다.
@CacheEvict(key = "#studyGroupId", value = STUDYGROUP_LIST, cacheManager = "redisCacheManager")
@Transactional
@Override
public void deleteById(Long studyGroupId) {
studyGroupRepository.deleteById(studyGroupId);
}