Spring Boot + AWS ElastiCache for Redis
AWS ElastiCache for Redis Cluster 생성
자세한 방법은 AWS ElastiCache 가이드 참고.
요약
- VPC Subnet Group 생성
- Redis Cache Cluster 생성
- 보안 그룹 설정에 Redis 관련 Port 추가
Spring Boot + Redis 연동 설정
Redis 관련 의존성 추가
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
compile group: 'redis.clients', name: 'jedis', version: '3.3.0'
application.yml 수정
spring:
redis:
host: [AWS ElastiCache End-Point Host url]
port: 6379
Redis Config 추가
@RequiredArgsConstructor
@EnableRedisRepositories
@Configuration
public class RedisConfiguration {
@Value("${spring.redis.host}")
private String redisHost;
@Value("${spring.redis.port}")
private int redisPort;
@Bean
JedisConnectionFactory jedisConnectionFactory() {
RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration(redisHost, redisPort);
return new JedisConnectionFactory(redisStandaloneConfiguration);
}
@Bean(value = "redisTemplate")
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory);
return redisTemplate;
}
@Primary
@Bean(name = "cacheManager")
public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) {
/**
* Cache 기본 설정
*/
RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig()
.disableCachingNullValues() // Null Value 는 Cache 사용하지 않음
.entryTtl(Duration.ofSeconds(CacheKey.DEFAULT_EXPIRE_SEC)) // Cache 의 기본 유효시간 설정(60sec)
.computePrefixWith(CacheKeyPrefix.simple()) // Cache Key 의 Prefix 설정(name + "::")
// Redis Cache 데이터 저장방식을 StringSerializer 로 설정
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()));
/**
* Cache 상세 설정
* - Cache default expire 시간 설정
*/
Map<String, RedisCacheConfiguration> cacheConfigurations = new HashMap<>();
cacheConfigurations.put(CacheKey.USER, RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(CacheKey.USER_EXPIRE_SEC)));
cacheConfigurations.put(CacheKey.BOARD, RedisCacheConfiguration.defaultCacheConfig().entryTtl(Duration.ofSeconds(CacheKey.BOARD_EXPIRE_SEC)));
return RedisCacheManager.RedisCacheManagerBuilder
.fromConnectionFactory(redisConnectionFactory)
.cacheDefaults(configuration)
.withInitialCacheConfigurations(cacheConfigurations)
.build();
}
}
Entity Redis 설정
Caching 객체 Serializable
Caching 객체 Serializable 하는 이유
Redis
에 객체를 저장하면 내부적으로 직렬화하여 저장Entity
에Serializable
을 선언하지 않으면 오류 발생 가능
@Entity
public class Board implements Serializable {
...
}
Lazy Loading False
Lazy Loading false 처리 하는 이유
- Entity 객체내에서 연관관계 Mapping에 의해 Lazy(지연) Loading 되는 경우 오류 발생 가능
@Proxy(lazy = false)
public class User implements Serializable {
...
}
CRUD Methods Caching 처리
Caching 처리 관련 Annotation
Annotation | 설명 |
---|---|
@Cacheable |
Cache 가 존재하면 요청된 Method 를 실행하지 않고 Cache 데이터를 반환 처리 |
@CachePut |
Cache 에 데이터를 넣거나 수정시 사용. Method 의 반환값이 Cache 에 없으면 저장하고, 있는 경우엔 갱신 처리 |
@CacheEvict |
Cache 삭제 |
@Caching |
여러개의 Cache Annotation 을 실행되어야 할 때 사용 |
Annotation 옵션 설명
value = CacheKey.BOARD
: 저장시 사용되는 Key Namekey = "#id"
:value
옵션에서 선언된 Key Name 과 결합 (ex. ‘board::1’)unless = "#result == null"
: 결과가null
이 아닌 경우만 Caching 처리condition = "#id > 10"
: 간단한 조건문에 따라 Caching 처리
Cache 처리의 또다른 방법. CacheService 추가
Caching
처리해주는 Service- 왜
CacheService
가 필요한가?- 요청받은
Method
의 인자값으로Cache Key
를 조합할 수 없을 때가 있기 때문 Proxy
의 특성상 같은 객체내에서는Caching
처리된Method
호출시 동작하지 않기 때문
- 요청받은
Custom Key Generator
CustomKeyGenerator.java
public class CustomKeyGenerator {
public static Object create(Object o1) {
return "FRONT:" + o1;
}
public static Object create(Object o1, Object o2) {
return "FRONT:" + o1 + ":" + o2;
}
}
CustomKeyGenerator 이용한 Caching
@Cacheable(value = CacheKey.BOARD, key = "T(com.demo.restapi.config.redis.CustomKeyGenerator).create(#id)", unless = "#result == null")
Reference keyholesoftware.com [Using Amazon ElastiCache For Redis]