오늘은 redis 서버를 쓰기/읽기 전용으로 분리 구성해보았습니다.
기존에는 redis 서버를 한대만 두었는데, 아직까지 이유는 파악하지 못했지만 갑자기 테스트용 redis 서버가 읽기 전용으로 인식되어, set이 불가능한 상태가 되었습니다.
우선 이 에러와 관련 없이, redis 서버에 장애가 발생했을 때 대처할 방법이 필요했었기 때문에 구조를 분리하게 되었습니다.
구성할 redis 노드는 아래와 같습니다.
(노드 : 포트)
main : 6379
replica1 : 6000
replica2 : 6001
이렇게 총 3개의 서버를 구성하겠습니다.
먼저, 설정 파일에 아래 코드를 추가합니다.
replicaof <main IP> <main Port>
저는 docker-compose를 사용하여 컨테이너로 띄울 것이기 때문에, host IP 부분에 컨테이너 이름을 넣어주었습니다.
다음은 도커 컴포즈를 작성합니다.
version: '3.8'
services:
redis-main:
container_name: main
image: redis:latest
ports:
- 6379:6379
redis-replica1:
container_name: rep1
image: redis:latest
volumes:
- /home/ec2-user/conf/:/data
ports:
- 6000:6379
command: redis-server /data/redis.conf
redis-replica2:
container_name: rep2
image: redis:latest
volumes:
- /home/ec2-user/conf/:/data
ports:
- 6001:6379
command: redis-server /data/redis.conf
#redis
redis:
main:
host: 127.0.0.1
port: 6379
replicas:
- host: 127.0.0.1
port: 6000
- host: 127.0.0.1
port: 6001
redis의 호스트, 포트 정보를 설정하기 위해 yml 또는 properties 파일에 위와 같이 추가해줍니다.
@Data
@ConfigurationProperties(prefix = "redis")
@Configuration
public class RedisProperties {
private String host;
private int port;
private RedisProperties main;
private List<RedisProperties> replicas;
}
값을 세팅하기 위해 ConfigurationProperties를 구성합니다.
@RequiredArgsConstructor
@Configuration
public class RedisConfig {
final RedisProperties properties;
@Bean
public LettuceConnectionFactory redisConnectionFactory() {
LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
.readFrom(ReadFrom.REPLICA_PREFERRED)
.build();
RedisStaticMasterReplicaConfiguration staticMasterReplicaConfiguration =
new RedisStaticMasterReplicaConfiguration(properties.getMain().getHost(), properties.getMain().getPort());
properties.getReplicas().forEach(replica -> staticMasterReplicaConfiguration.addNode(replica.getHost(), replica.getPort()));
return new LettuceConnectionFactory(staticMasterReplicaConfiguration, clientConfig);
}
}
마지막으로 세팅한 properties 값들로 redis 커넥션을 완성합니다.
@Test
@DisplayName("redis main set/get test")
void redis_main_set_get_test() {
//given
String key = "key";
String value = "value";
redisService.setValues(key, value);
//when
String getValue = redisService.getValues(key);
//then
assertThat(value).isEqualTo(getValue);
redisService.deleteValues(key);
}
redis 서버에 set, get을 해본 결과 정상적으로 테스트가 성공하는 것을 확인할 수 있습니다.
좀 더 확실하게 확인하고 싶으시면, 실행한 도커 컨테이너로 접근하여
main에 값을 set 했을 때 replica 서버에도 값이 set 되는가,
replica 에서 set 했을때 error가 발생하는가
등을 확인해보시면 될 것 같습니다! 저는 모두 정상임을 확인했고, 테스트 완료 후 운영 서버에도 반영하였습니다.
참고 : https://faun.pub/redis-master-slave-configuration-and-tested-in-spring-boot-3a68e7314b90