본문 바로가기
문제 해결, 기술 비교/개인프로젝트(북클럽)

redis 저장소를 cache, session 전용으로 분리하기

코동이 2022. 10. 1.

개요


현재 저의 개인 프로젝트에서는 redis에 캐시, 세션(+rememberme token)을 모두 하나의 redis에 저장하고 있습니다. 최근에 redis의 replica, mysql의 replica를 공부하면서 장애를 대비하는 분산 환경을 잘 구비해야겠다는 사실을 깨닫고 있었던 찰나에, redis에 모든 정보를 관리하고 있다는 것을 발견했습니다. 따라서, 이번에는 너무 하나의 redis에 데이터가 몰리지 않도록 다중 redis 설정을 해보겠습니다.

 

 

 

기존에는 어떻게 redis가 작업을 처리하고 있을까?


 현재 하나의 redis에 캐시용, 세션용 데이터가 모두 들어오고 있습니다. 많은 데이터들이 한번에 redis에 저장, 조회되면 대용량의 경우에는 성능에 이슈가 생길 수가 있습니다. 따라서 캐시용과 세션용을 분리하려고 합니다.

 

 

하나의 저장소만 사용

 

아래의 keys * 명령어를 통해 key들을 보면, cache용과 session 정보가 섞여 있습니다.

 

cache용 + session용

 

 

대용량 요청 시, redis 부하를 줄이는 방법은?


대용량 요청이 오면, redis 부하를 줄이기 위해서 redis를 분리하려고 합니다. 하나는 캐시 전용으로, 하나는 세션 전용으로 나눕니다. 분리를 통해 대용량 요청에서 좀 더 안정적으로 요청을 처리할 수 있으며, 만약 하나의 시스템에서 장애가 났더라도 redis를 하나만 사용할 때보다는 훨씬 장애에 대응하기가 수월합니다.

 

로컬에서는 redis를 2개 띄울 수 없습니다. 따라서 1개는 설치형으로 진행하고, 다른 하나는 docker를 사용해서 만들어보겠스니다.

 

도커 명령어 설명은 생략하겠으나, 아래에 <port>에 연결하고 싶은 포트를 이용하여 실행 할 수 있습니다.

 

$ docker run --name redis-session -d -p <port>:6379 redis

 

이제 총 2개의 redis 서버가 실행됩니다.

 

 

 

레디스를 각각 분리

 

 

이제 실제 프로젝트에서 코드로 적용해보겠습니다.

 

코드로 적용해보기


프로젝트에 적용하기 위해서 총 3개의 작업이 필요합니다.

 

  • application.yml에 각각 redis 정보 추가하기
  • 캐시 전용 설정파일 만들기
  • 세션 전용 설정파일 만들기

 

먼저 application.yml에서 2개의 redis port, ip정보를 설정합니다.

 

application.yml

 

 

캐시용 설정 파일을 수정합니다.

 

@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
public class RedisCacheConfig {
	@Value("${spring.redis.cache.host}")
	private String hostName;

	@Value("${spring.redis.cache.port}")
	private int port;

	@Bean
	public RedisConnectionFactory redisCacheConnectionFactory() {
		RedisStandaloneConfiguration redisStandaloneConfiguration 
        	= new RedisStandaloneConfiguration();
		redisStandaloneConfiguration.setHostName(hostName);
		redisStandaloneConfiguration.setPort(port);
		return new LettuceConnectionFactory(redisStandaloneConfiguration);
	}
    ...
}

 

@Value를 사용해, application.yml에서 설정했던 host, port정보를 가져와 직접 redis 정보를 설정합니다.

 

 

세션용 파일을 수정합니다.

 

@Configuration
@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800)
public class RedisSessionConfig {
	@Value("${spring.redis.session.host}")
	private String hostName;

	@Value("${spring.redis.session.port}")
	private int port;

	@Primary
	@Bean
	public RedisConnectionFactory redisSessionConnectionFactory() {
		RedisStandaloneConfiguration redisStandaloneConfiguration 
        		= new RedisStandaloneConfiguration();
		redisStandaloneConfiguration.setHostName(hostName);
		redisStandaloneConfiguration.setPort(port);
		return new LettuceConnectionFactory(redisStandaloneConfiguration);
	}

    ...
}

 

@Value를 통해, application.yml에 설정한 host, port 정보를 가져와 직접 redis 정보를 설정합니다.

 

 

마무리


이번 시간 redis의 부하를 줄이기 위해 하나만 사용했던 redis를 2개로 분리하였습니다.

이를 통해서 장애 발생 시, 캐시와 세션이 서로 영향을 미치지 않도록 하여 데이터를 보호할 수 있었습니다.

또한 캐시 메모리도 분산되어서 더 많은 정보들을 캐시로 관리할 수 있습니다.

반응형