아빠는 개발자

[java] API - redis cache for method 본문

Java/API

[java] API - redis cache for method

father6019 2023. 10. 13. 21:23
728x90
반응형

검색결과중 일부 메소드에서 처리하는 데이터 들만 캐싱해야하는 상황..  일단 구현해보자

https://father-lys.tistory.com/42 에서 세팅한 redis 정보를 활용

 

우선 컨드롤러 생성 CacheService 의 getCaches 를 호출

package com.doo.aqqle.controller;


import com.doo.aqqle.model.CommonResult;
import com.doo.aqqle.service.CacheService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;


@RestController
@Api(tags = "3. Cache Apis")
@RequestMapping("api/search")
@RequiredArgsConstructor
public class CacheRestController {

    private final CacheService cacheService;

    @CrossOrigin("*")
    @ApiOperation(value = "search", notes = "검색")
    @GetMapping("cache")
    public CommonResult getDatas(
            @ApiParam(value = "countryCode") @RequestParam(value = "countryCode", defaultValue = "KR", required = true) @Validated final String countryCode
    ) {
        return cacheService.getCaches(countryCode);
    }

}

CacheService 생성 CacheCompo 의 메소드 들을 호출해서 데이터를 받아옴

package com.doo.aqqle.service;


import com.doo.aqqle.component.CacheCompo;
import com.doo.aqqle.model.CommonResult;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;

@Service
@RequiredArgsConstructor
public class CacheService {

    private final CacheCompo cacheCompo;
    private final ResponseService responseService;
    public CommonResult getCaches(String countryCode) {
        List<String> responseList = new ArrayList<>();
            responseList.add(cacheCompo.getCacheName(countryCode).getName());
            responseList.add(cacheCompo.getCacheFilter(countryCode).getName());
            responseList.add(cacheCompo.getCacheAttr(countryCode).getName());
            responseList.add(cacheCompo.getCacheAggs(countryCode).getName());
        return responseService.getListResult(responseList);
    }
}

 

CacheCompo 우선은 모든메소드의 데이터를 캐싱해서 각각 조건에 맞게 캐싱되고 있는지 확인 

package com.doo.aqqle.component;

import com.doo.aqqle.common.CacheKey;
import com.doo.aqqle.model.CacheResponse;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Component;

@Component
public class CacheCompo {

    @Cacheable(value = CacheKey.NAME, key = "#countryCode", unless = "#result == null")
    public CacheResponse getCacheName (String countryCode){
        System.out.println("cacheName");
        CacheResponse cacheResponse = new CacheResponse();
        cacheResponse.setName("cacheName");
        return cacheResponse;
    }

    @Cacheable(value = CacheKey.FILTER, key = "#countryCode", unless = "#result == null")
    public CacheResponse getCacheFilter (String countryCode){
        System.out.println("cacheFilter");
        CacheResponse cacheResponse = new CacheResponse();
        cacheResponse.setName("cacheFilter");
        return cacheResponse;
    }

    @Cacheable(value = CacheKey.ATTR, key = "#countryCode", unless = "#result == null")
    public CacheResponse getCacheAttr (String countryCode){
        System.out.println("cacheAttr");
        CacheResponse cacheResponse = new CacheResponse();
        cacheResponse.setName("cacheAttr");
        return cacheResponse;
    }

    @Cacheable(value = CacheKey.AGGS, key = "#countryCode", unless = "#result == null")
    public CacheResponse getCacheAggs (String countryCode){
        System.out.println("cacheAggs");
        CacheResponse cacheResponse = new CacheResponse();
        cacheResponse.setName("cacheAggs");
        return cacheResponse;
    }

}

CacheKey 파일 생성

package com.doo.aqqle.common;

public class CacheKey {

    public static final int DEFAULT_EXPIRE_SEC = 60; // 1 minutes
    public static final String NAME = "name";
    public static final String LOCATION = "location";
    public static final int NAME_EXPIRE_SEC = 60 * 3; // 3minutes
    public static final String FILTER = "filter";
    public static final int FILTER_EXPIRE_SEC = 60 * 2; // 2 minutes
    public static final String ATTR = "attr";
    public static final String AGGS = "aggs";
    public static final int AGGS_EXPIRE_SEC = 60 * 5; // 5 minutes

}

 

RedisConfig 수정 - 지난글에서 location 관련 설정과 동일하게 각 메소드들이 사용할 캐시 key에 대한 유효시간 설정 

package com.doo.aqqle.config;

import com.doo.aqqle.common.CacheKey;
import lombok.RequiredArgsConstructor;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.CacheKeyPrefix;
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.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.time.Duration;
import java.util.HashMap;
import java.util.Map;

@RequiredArgsConstructor
@EnableCaching
@Configuration
public class RedisConfig {

    @Bean(name = "cacheManager")
    public RedisCacheManager cacheManager(RedisConnectionFactory connectionFactory) {

        RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig()
                .disableCachingNullValues()
                .entryTtl(Duration.ofSeconds(CacheKey.DEFAULT_EXPIRE_SEC))
                .computePrefixWith(CacheKeyPrefix.simple())
                .serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));

        Map<String, RedisCacheConfiguration> cacheConfigurations = new HashMap<>();
        // 캐시 유효시간 설정
        cacheConfigurations.put(CacheKey.NAME, RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(CacheKey.NAME_EXPIRE_SEC)));
        cacheConfigurations.put(CacheKey.LOCATION, RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(CacheKey.DEFAULT_EXPIRE_SEC)));
        cacheConfigurations.put(CacheKey.FILTER, RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(CacheKey.FILTER_EXPIRE_SEC)));
        cacheConfigurations.put(CacheKey.ATTR, RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(CacheKey.AGGS_EXPIRE_SEC)));
        cacheConfigurations.put(CacheKey.AGGS, RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(Duration.ofSeconds(CacheKey.AGGS_EXPIRE_SEC)));

        return RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(connectionFactory).cacheDefaults(configuration)
                .withInitialCacheConfigurations(cacheConfigurations).build();
    }
}
1회  2회 3회
각 메소드에서 찍은 텍스트 들이 1번씩 출력 
- 캐시 생성
cacheFilter 는 캐시가 만료되어 1회 출력, 
나머지는 캐시 사용중 
모든캐시가 만료되어 각 1회씩 더 출력

이제 검색쿼리를 넣고 일부 메소드 들만 캐싱되게 처리 해서 데이터와 응답시간을 확인 

728x90
반응형