728x90
반응형
build.gradle에 추가
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
application.properties에 추가
spring.cache.type=redis
spring.data.redis.host=
spring.data.redis.port=
spring.data.redis.password=
spring.data.redis.repositories.enabled=false
# spring.cache.redis.time-to-live=600000
expire.defaultTime=36288000
mainApplication 에 추가
@EnableCaching
RedisConfig class 를 만들어준다.
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
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.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
@Configuration
public class RedisConfig {
@Value("${spring.data.redis.host}")
private String redisHost;
@Value("${spring.data.redis.port}")
private int redisPort;
@Value("${spring.data.redis.password}")
private String redisPwd;
@Value("${expire.defaultTime}")
private long defaultExpireSecond;
@Bean
public ObjectMapper objectMapper() {
ObjectMapper mapper = new ObjectMapper();
//TimeStamp 를 설정하지 못하게 disable 설정
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
//날짜 인식 가능하게
mapper.registerModules(new JavaTimeModule(), new Jdk8Module());
return mapper;
}
@Bean
public RedisConnectionFactory redisConnectionFactory() {
//redis의 실제 연결 정보
RedisStandaloneConfiguration redisStandaloneConfiguration
= new RedisStandaloneConfiguration();
redisStandaloneConfiguration.setPort(redisPort);
redisStandaloneConfiguration.setHostName(redisHost);
redisStandaloneConfiguration.setPassword(redisPwd);
//redisConnectionFactory 의 구현체. lettuce 가 비동기 동작으로 더 빠르다.
LettuceConnectionFactory lettuceConnectionFactory =
new LettuceConnectionFactory(redisStandaloneConfiguration);
return lettuceConnectionFactory;
}
@Bean
public RedisCacheManager redisCacheManager(RedisConnectionFactory redisConnectionFactory,
//서버간 통신을 위한 직렬화. 역직렬화를 해주는 ObjectMapper
ObjectMapper objectMapper) {
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig()
.disableCachingNullValues()
.entryTtl(Duration.ofSeconds(defaultExpireSecond))
//직렬화를 통해 통신하게 설정
.serializeKeysWith(RedisSerializationContext
.SerializationPair
.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair
.fromSerializer(new GenericJackson2JsonRedisSerializer(objectMapper)));
return RedisCacheManager.RedisCacheManagerBuilder.fromConnectionFactory(
redisConnectionFactory)
.cacheDefaults(configuration).build();
}
}
ServiceImpl 에 적용
@Async
@Cacheable(value = "getPosts",
key = "'getPosts' + #request.getName() + #request.getCategoryId()",
unless = "#result == null")
@Override
public List<PostDTO> getPosts(PostSearchRequest request) {
List<PostDTO> dtos = null;
try {
dtos = postSearchMapper.selectPosts(request);
} catch (RuntimeException e) {
log.error("select 실패 {}", e
.getMessage());
log.error(e);
}
return dtos;
}
}
unless = "#result == null" 이 없다면 검색 단어가 없을 때 NPE 가 발생한다.
@Async? :
비동기적 처리를 도와주는 어노테이션. 캐시가 존재할 때는 즉시 응답, 없을 때는 비동기적으로 데이터 조회한다.
클라이언트의 요청 -> 캐시 확인 -> 캐시가 없다면 DB 조회해 비동기적으로 데이터 가져오고, 캐시에 저장.
메인 스레드는 데이터의 조회를 기다리지 않고 즉시 응답하고, 실제 데이터 조회 작업은 백그라운드에서 수행한다.
복잡한 로직이 있었다면 사용하기를 주저했겠지만, 간단한 검색 기능이라 속도 향상을 위해 사용해보았다.
현재 게시글:
검색:
{
"name": "update",
"contents":"",
"categoryId":2,
"sortStatus":"NEWEST"
}
결과:
{
"dtos": [
{
"id": 3,
"name": "update post",
"contents": "dsfd content",
"views": 0,
"categoryId": 2,
"userId": 0,
"sortStatus": null
}
]
}
CMD:
docker exec -it redis redis-cli
docker exec -it [이름] redis-cli
KEYS *
결과 확인.
728x90
'JAVA > 프로젝트' 카테고리의 다른 글
성능 테스트 - Locust 설치, 이론 (1) | 2024.11.20 |
---|---|
성능 테스트 진행- 테스트 종류와 툴, 진행할 시나리오 (0) | 2024.11.18 |
로그인 AOP 적용 (1) | 2024.11.16 |
대규모 트래픽을 고려한 프로젝트 기획 - 스택, 목적, 기능, 컨벤션, ERD (1) | 2024.11.14 |
리팩토링: 캐시 적용 중 NPE, key, keyGenerator, 캐시 초기화, 검색기능 캐시 (1) | 2024.09.17 |