Spring boot에서 Redis 사용기 ..
Spring Boot에서 Redis를 사용한 것에 대해 기록하려고 한다.
레디스를 왜 사용할까 ?
서비스가 커지고 트래픽이 많아질 수록 백엔드 서버를 유지하기 위해서는 많은 것을 고려해야한다.
흔히 고려할 수 있는 포인트는 불필요한 I/O를 줄이는 것이다. 변하지 않는 결과를 굳이 DB에서 조회하기 보단 캐싱해서 빠르게 조회하는 것이 성능면에서 좋을 것이다.
물론 애플리케이션 내의 캐싱을 사용할 수 있지만, 서버를 여러개 띄우게 되면 해당 값들은 공유할 수 없다. redis를 사용하면 서버를 여러대 띄운 환경에서도 캐시 메모리를 공유할 수 있다.
레디스 특징
in-memory 데이터베이스
key-value 형태의 데이터베이스
single-thread
다양한 command제공
높은 availability를 위한 옵션이 존재 - 센티널, 레디스 클러스터
docker 에서 redis 환경 구축
- Docker에서 Redis Image pull
docker image pull redis
- Docker에서 redis run
sudo docker run -p 6379:6379 redis
- Redis network 구축하는 방법도 있는데, 진행한 프로젝트에서는 필요가 없을 것 같아 사용하지 않았다.
- redis 컨테이너에 접속 후
redis-cli
를 통해서 레디스의 데이터를 조회할 수 있다.
Spring boot와 redis 연결
Spring boot의 build.gradle에서 redis 관련 의존성을 추가한다.
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
application.yml에 redis host&port 정보 기입
spring:
redis:
host: localhost
port: 6379
Redis Configuration 클래스 정의
@Configuration
@EnableRedisRepositories
@RequiredArgsConstructor
public class RedisConfiguration {
// application.yml에 레디스 정보 관리 prefix = "spring.redis"
private final RedisProperties redisProperties;
@Bean
public RedisConnectionFactory redisConnectionFactory() {
RedisURI redisURI = RedisURI.create(redisProperties.getHost(),redisProperties.getPort());
// 레디스와 애플리케이션을 연결을 위한 라이브러리는 Jedis 와 Lettuce가 있다. 요즘은 Lettuce을 많이 사용한다.
org.springframework.data.redis.connection.RedisConfiguration configuration = LettuceConnectionFactory.createRedisConfiguration(redisURI);
LettuceConnectionFactory factory = new LettuceConnectionFactory(configuration);
factory.afterPropertiesSet(); // initialized
return factory;
}
// 레디스 커맨드를 쉽게 사용할 수 있는 클래스 RedisTemplate<Key,Value> , 데이터 변경이 잦은 데이터는 캐싱 장점이 없다.
// 자주 사용하는 데이터를 캐싱하는 것이 좋다.
@Bean // UserEntity보다 User를 캐싱하는 것이 더 좋다고 판단.
public RedisTemplate<String, User> userRedisTemplate(RedisConnectionFactory redisConnectionFactory) {
RedisTemplate<String, User> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory); // setConnectionFactory - 실제 레디스 서버에 대한 정보를 가짐
redisTemplate.setKeySerializer(new StringRedisSerializer()); // 레디스에 데이터 저장시 serializer 필요
redisTemplate.setHashValueSerializer(new Jackson2JsonRedisSerializer<User>(User.class));
return redisTemplate;
}
}
- RedisConnectionFactory 클래스를 Bean으로 등록
- Spring Boot에서는 RedisTemplate<Key,Value>를 제공하는데 이를 사용하여 레디스를 간편히 사용할 수 있다.
- setKeySerializer, setValueSerializer 설정하여 직렬화 방법을 지정해준다.
Redis로 데이터 조회하는 코드
@Slf4j
@Repository
@RequiredArgsConstructor
public class UserCacheRepository {
private final RedisTemplate<String, User> userRedisTemplate;
private static final Duration USER_CACHE_TTL = Duration.ofDays(3); // TTL 3일 설정
// 레디스의 경우 TTL (일정 기간 지난 후 expired) 를 걸어두는 것이 좋다.
// 사용 접근하지 않은 캐시를 계속 가지고 있을 필요는 없다. 레디스 공간을 효율적 사용을 위해... TTL 설정
// redisTemplate.opsForValue(); ->기본적인 get/set 제공
public void setUser(User user) {
String key = getKey(user.getUsername());
log.info("Set User to Redis {}:{}",key,user);
userRedisTemplate.opsForValue().set(getKey(user.getUsername()),user,USER_CACHE_TTL);
}
public Optional<User> getUser(String userName) {
String key = getKey(userName);
User user = userRedisTemplate.opsForValue().get(key);
log.info("Get data from Redis {} , {}",key,user);
return Optional.ofNullable(user);
}
// 서비스가 커지면 user 정보뿐만 아니라 다양한 데이터를 캐싱하게 된다. 이 때 구분을 위해 레디스 내에서 prefix를 지정하여 사용하는 것이 좋다.
private String getKey(String userName) {
return "USER:" + userName;
}
}
'Spring' 카테고리의 다른 글
[JPA] 프록시 (1) | 2023.10.09 |
---|---|
[JPA]영속성 컨텍스트 (0) | 2023.09.24 |
[JPA] 더티체킹 (0) | 2023.09.11 |
Spring profile (0) | 2023.07.09 |
댓글