Redis - @Cacheable, @CacheEvict

devdo·2022년 5월 27일
1

서버 백앤드 스터디

목록 보기
14/16

Redis의 RedisTemplate, @Cacheable, @CacheEvict 개념을 정리해봅니다.

그전에 설정작업

0) Redis 설치및 run
https://velog.io/@mooh2jj/Redis-설치 참고

1) dependency & propertire

  • build.gradle
// 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'
  • application.yml
spring:
  redis:
    host: localhost
    port: 6379 # redis 기본포트 6379

RedisTemplate 사용

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 을 알아보자. TTLcache 만료시간을 뜻한다.
시간타입을, second, Day 등 바꿀 수도 있다.

// entryTtl 설정
cacheConfigurationMap.put(RedisCacheKey.STUDYGROUP_LIST,
redisCacheConfiguration.entryTtl(Duration.ofSeconds(180L)));

@Cacheable & @CacheEvict 처리

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);
    }


참고

profile
배운 것을 기록합니다.

0개의 댓글