오늘은 팀프로젝트를 하면서 적용한 REDIS DB 여러개 관리하는 방법을 포스팅 하려고합 니다.
상황은 이러 했습니다.
제가 Redis Server를 띄워서 데이터를 관리하고 있었는데, 백엔드를 같이 담당하던 팀원분이
자신도 Redis에 데이터를 저장하고 싶다는 것이었습니다.
하지만 제가 Redis 상에서 다루고 있던 데이터들은 게임과 관련된 데이터였고,
팀원분께서 다루고자 하는 데이터는 회원가입, 유저인증에 관련된 데이터였습니다.
데이터의 관심사가 다르므로 이를 분리해야 할 것 같다는 생각을 하게 되었습니다.
그래서 정보를 찾다가, Redis 에서 Database 를 여러대로 나눌 수 있다는 사실을 알게됩니다.
SELECT 1 이라는 명령어 중 1은 DB의 인덱스를 뜻합니다.
즉, REDIS 에서는 총 0부터 15까지 16개의 데이터베이스를 분리하여 운영할 수 있다는 뜻 입니다.
그럼 Springboot 에서 0번, 1번 인덱스 DB에 데이터를 저장하는 방법을 알려드리겠습니다.
우선 Configuration 파일을 건드려야 할텐데, 기존에 사용하던 Configuration 안에는
다음과 같이 Bean이 등록되어 있었습니다.
@Bean
public RedisConnectionFactory redisConnectionFactory(){
final RedisStandaloneConfiguration redisStandaloneConfiguration =
new RedisStandaloneConfiguration();
redisStandaloneConfiguration.setHostName(redisHost);
redisStandaloneConfiguration.setPort(redisPort);
return new LettuceConnectionFactory(redisStandaloneConfiguration);
}
@Bean
public RedisTemplate<String, Object> redisTemplate(){
RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.setEnableTransactionSupport(true);
redisTemplate.setConnectionFactory(redisConnectionFactory());
return redisTemplate;
}
redis와 연결할 때, application.yml 에 작성한 redisHost와 redisPort 만 지정해서
연결했기에 default 로 설정된 DB에 데이터가 저장됩니다.
우선 redisConnectionFactory 에서 데이터를 저장할 DB 인덱스를 지정해주도록 합니다.
@Bean
public RedisConnectionFactory redisConnectionFactory(int dbIndex){
final RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
redisStandaloneConfiguration.setHostName(redisHost);
redisStandaloneConfiguration.setPort(redisPort);
//DB 인덱스 추가
redisStandaloneConfiguration.setDatabase(dbIndex);
return new LettuceConnectionFactory(redisStandaloneConfiguration);
}
Parameter로 dbIndex 값을 받아 DB 의 인덱스를 지정해주는 모습입니다.
저는 redis에서 main이 되는 DB를 mainRedis, sub로 사용될 DB를 subRedis 라고 이름지었습니다.
그래서 mainRedisConfig, subRedisConfig 클래스를 각각 정의해 사용했습니다.
@Configuration
public class MainRedisConfig extends RedisConfig {
@Bean
@Primary
public RedisConnectionFactory mainRedisConnectionFactory() {
return redisConnectionFactory(0);
}
@Bean
public RedisTemplate<String, Object> redisTemplate(){
RedisTemplate<String,Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.setEnableTransactionSupport(true);
redisTemplate.setConnectionFactory(mainRedisConnectionFactory());
return redisTemplate;
}
}
@Configuration
public class SubRedisConfig extends RedisConfig{
@Bean
public RedisConnectionFactory subRedisConnectionFactory() {
return redisConnectionFactory(1);
}
@Bean
public RedisTemplate<String, String> redisTemplate(){
RedisTemplate<String,String> redisTemplate = new RedisTemplate<>();
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new StringRedisSerializer());
redisTemplate.setEnableTransactionSupport(true);
redisTemplate.setConnectionFactory(subRedisConnectionFactory());
return redisTemplate;
}
}
두 코드를 비교해보면, 크게 두가지가 다릅니다.
우선, mainRedisConfig 는 RedisConnectionFactory에서 0번째 인덱스 DB를 사용하겠다 선언하였고,
subRedisConfig 에서는 1번째 인덱스 DB를 사용하겠다 선언합니다.
또 다른 한가지는, RedisTemplate에서 키와 밸류값을 <String, Object>, <String, String> 으로 받는다는 점입니다.
만약 두개의 DB에서 <String, String> 타입의 RedisTemplate를 사용한다면, @Qualifier 어노테이션을 통해
Bean에 추가 구분자를 달아줘야합니다.
RedisTemplate가 각각 다른 제너릭타입이므로,
RedisService 또한 분리해 만들어줍니다.
@Service
@Slf4j
public class MainRedisService {
@Autowired
private RedisTemplate<String,Object> redisTemplate;
private HashOperations<String,String,Object> hashOps;
/*
* HASH 관련 함수
* */
@Autowired
public void setHashOperations(){
this.hashOps = redisTemplate.opsForHash();
}
public void put(String key, String hashKey, Object value) {
hashOps.put(key, hashKey, value);
}
public Object get(String key, String hashKey) {
return hashOps.get(key, hashKey);
}
//.....
}
@Service
@Slf4j
public class SubRedisService {
@Autowired
private RedisTemplate<String,String> redisTemplate;
public void setValue(String key, String value){redisTemplate.opsForValue().set(key,value,1, TimeUnit.MINUTES);}
public String getValue(String key){return redisTemplate.opsForValue().get(key);}
}
MainRedisService에서는 <String,Object>
SubRedisService에서는 <String,String>
이렇게 주입 받고있습니다.
이렇게 셋팅을 해두고, 비즈니스 로직을 통해 Redis에 데이터를 저장해보겠습니다.
각 인덱스 별 DB에 데이터가 잘 저장되는 것을 확인할 수 있습니다.