모든 저장소가 그렇듯 Redis에서도 HA(High Availability)를 지원한다. Lettuce 사용시, 일반적인 설정으로는 master 에서만 read/write 작업을 하기 때문에, replica 에서도 read 작업을 수행하기 위해서 추가적인 설정이 필요하다.
HA 란 고가용성 이다.
가용성은 시스템 고장 발생 시 얼마나 빠른 시간내에 치료가 되어 다시 정상적으로 서비스할 수 있는 상태인지를 분석하는 척도이다. 따라서 HA 구성이란 이러한 가용성을 극대화 시키는 구성을 말하는 것으로서 '클러스터링, 이중화, RAID'는 범위로 보면 HA 를 이루기 위한 방식이라 볼 수 있습니다.
Redis는 고가용성(HA)를 위해 Replication(Master-Slave) 구조를 지원하며, 추가적으로 Sentinel or Cluster 구성 방법을 제공한다.
@Configuration
public class RedisConfig {
@Value("${spring.data.redis.primary.host}")
private String primaryHost;
@Value("${spring.data.redis.primary.port}")
private int primaryPort;
@Value("${spring.data.redis.replica.host}")
private String replicaHost;
@Value("${spring.data.redis.replica.port}")
private int replicaPort;
@Bean
public RedisConnectionFactory redisConnectionFactory() {
LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
.readFrom(ReadFrom.REPLICA_PREFERRED)
.build();
var redisConnect = new RedisStaticMasterReplicaConfiguration(primaryHost, primaryPort);
redisConnect.addNode(replicaHost, replicaPort);
return new LettuceConnectionFactory(
redisConnect,
clientConfig
);
}
@Bean
public RedisTemplate<String, Object> redisTemplate() {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(redisConnectionFactory());
redisTemplate.setKeySerializer(new StringRedisSerializer());
redisTemplate.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return redisTemplate;
}
...
ReadFrom | 설명 |
---|---|
ReadFrom.UPSTREAM | 현재 master 노드에서만 읽음. (default) |
ReadFrom.ANY | 클러스터의 아무 노드에서나 읽음. |
ReadFrom.ANY_REPLICA | 클러스터의 아무 replica 노드에서나 읽음. |
ReadFrom.LOWEST_LATENCY | 가장 낮은 지연 시간을 가진 노드에서 읽음. |
ReadFrom.MASTER | 현재 master 노드에서만 읽음. |
ReadFrom.MASTER_PREFERRED | master 노드를 우선으로 읽음. 불가능할 경우, replica 노드에서 읽음. |
ReadFrom.REPLICA | replica 노드에서만 읽음 |
ReadFrom.REPLICA_PREFERRED | replica 노드를 우선으로 읽음. 불가능할 경우, master 노드에서 읽음. |
ReadFrom.UPSTREAM_PREFERRED | master 노드를 우선으로 읽음. 불가능할 경우, replica 노드에서 읽음. |
@Configuration
public class RedisConfig {
@Value("${spring.data.redis.primary.host}")
private String primaryHost;
@Value("${spring.data.redis.replica.host}")
private String replicaHost;
@Bean
public RedissonClient redissonClient() {
Config config = new Config();
config.useMasterSlaveServers()
.setMasterAddress(primaryHost)
.addSlaveAddress(replicaHost)
.setReadMode(ReadMode.SLAVE);
return Redisson.create(config);
}
@Bean
@Primary
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return template;
}
}
masterSlaveServersConfig:
idleConnectionTimeout: 10000
connectTimeout: 10000
timeout: 3000
...
loadBalancer: !<org.redisson.connection.balancer.RoundRobinLoadBalancer> {}
readMode: "SLAVE"
subscriptionMode: "SLAVE"
slaveAddresses:
- "redis://127.0.0.1:6381"
- "redis://127.0.0.1:6380"
masterAddress: "redis://127.0.0.1:6379"
database: 0
threads: 16
nettyThreads: 32
codec: !<org.redisson.codec.Kryo5Codec> {}
transportMode: "NIO"
설정 (Setting) | 설명 (Description) |
---|---|
SLAVE | replica 노드를 우선으로 읽음. 불가능할 경우, master 노드에서 읽음. (기본값) |
MASTER | 현재 master 노드에서만 읽음. |
MASTER_SLAVE | master와 replica 노드 모두에서 읽음. |