ChamomileGuides 3.0.4 Help

캐시 모듈(Redis) 활용 가이드

레디스 클러스터란

Redis cluster는 데이터를 자동으로 여러 개의 Redis 노드에 나누어 저장할 수 있는 방법을 제공한다. 또한 일부 노드가 죽거나 통신이 되지 않을 때에도 작업을 계속할 수 있는 가용성을 제공한다

장점

  1. 샤딩(Sharding)
    노드 간에 데이터 세트를 자동으로 분할할 수 있는 기능

  2. 가용성
    노드의 하위 집합에서 장애가 발생하거나 클러스터의 나머지 부분과 통신할 수 없을 때 작업을 계속할 수 있는 기능이다. 즉, 실제적인 측면에서 일부 노드가 실패하거나 통신할 수 없을 때도 정상적으로 작동한다. 그러나 더 큰 고장이 발생할 경우(예: 대부분의 마스터를 사용할 수 없는 경우) 클러스터 작동이 중지된다.

클러스터 구성도

3개 서버의 가상환경을 구축하고 아래와 같이 구조로 클러스터를 구성하겠습니다.

42424-images/image-20231129160506.png

서버 1에 문제가 생겨서 더 이상 통신이 되지 않는다면 자동으로 slave 노드 중 하나가 master가 되어 작업을 계속 할 수 있다.

특징

  1. 자동 분할: 클러스터에서는 데이터가 자동으로 분할되어 각 마스터 노드에 저장됩니다. 이는 키의 해시 값을 통해 결정됩니다.

  2. 데이터 접근: 클라이언트는 어느 노드에 접속하든 클러스터 전체의 데이터에 접근할 수 있습니다. 요청된 키가 해당 노드에 없는 경우, 클라이언트는 해당 키를 가진 노드로 리디렉션됩니다.

  3. 복제 및 고가용성: 각 마스터 노드는 하나 이상의 슬레이브 노드를 가질 수 있으며, 이들은 마스터 노드의 데이터를 복제합니다. 이를 통해 데이터의 안정성과 고가용성이 보장됩니다.

  4. 동기화: 마스터 노드와 슬레이브 노드 간에는 지속적인 데이터 동기화가 일어납니다. 이 과정을 통해 데이터의 일관성과 무결성이 보장됩니다.

  5. 자동 장애 전환: Redis 클러스터에서는 자동 장애 전환(Failover)이 가능합니다. 마스터 노드에 장애가 발생하면, 슬레이브 노드 중 하나가 자동으로 마스터 노드의 역할을 맡게 됩니다.

Docker 환경에서 Redis 클러스터 구축하기

  1. docker-compose.yml 설정

    version: '3' services: redis-master1: image: redis:6.0.9-alpine command: redis-server --port 3000 --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes ports: - 3000:3000 - 13000:13000 volumes: - redis-master1-data:/data networks: redis-net: ipv4_address: 172.27.0.10 redis-master2: image: redis:6.0.9-alpine command: redis-server --port 3001 --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes ports: - 3001:3001 - 13001:13001 volumes: - redis-master2-data:/data networks: redis-net: ipv4_address: 172.27.0.3 redis-master3: image: redis:6.0.9-alpine command: redis-server --port 3002 --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes ports: - 3002:3002 - 13002:13002 volumes: - redis-master3-data:/data networks: redis-net: ipv4_address: 172.27.0.4 redis-slave1: image: redis:6.0.9-alpine command: redis-server --port 3003 --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes ports: - 3003:3003 - 13003:13003 volumes: - redis-slave1-data:/data networks: redis-net: ipv4_address: 172.27.0.5 redis-slave2: image: redis:6.0.9-alpine command: redis-server --port 3004 --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes ports: - 3004:3004 - 13004:13004 volumes: - redis-slave2-data:/data networks: redis-net: ipv4_address: 172.27.0.6 redis-slave3: image: redis:6.0.9-alpine command: redis-server --port 3005 --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes ports: - 3005:3005 - 13005:13005 volumes: - redis-slave3-data:/data networks: redis-net: ipv4_address: 172.27.0.7 redis-cluster-init: image: redis:6.0.9-alpine command: > sh -c "sleep 10 && echo yes | redis-cli --cluster create 10.131.4.85:3000 10.131.4.85:3001 10.131.4.85:3002 10.131.4.85:3003 10.131.4.85:3004 10.131.4.85:3005 --cluster-replicas 1 --cluster-yes" depends_on: - redis-master1 - redis-master2 - redis-master3 - redis-slave1 - redis-slave2 - redis-slave3 networks: redis-net: driver: bridge ipam: config: - subnet: 172.27.0.0/16 volumes: redis-master1-data: redis-master2-data: redis-master3-data: redis-slave1-data: redis-slave2-data: redis-slave3-data:
    • Redis 마스터 노드: redis-master1, redis-master2, redis-master3이라는 세 개의 마스터 노드가 있다. 각각 다른 포트(3000, 3001, 3002)와 볼륨을 사용한다.

    • Redis 슬레이브 노드: redis-slave1, redis-slave2, redis-slave3이라는 세 개의 슬레이브 노드가 있으며, 이들도 각각 다른 포트(3003, 3004, 3005)와 볼륨을 사용한다.

    • 네트워킹: 모든 노드는 redis-net이라는 동일한 네트워크에 연결되어 있으며, 각 노드에는 고정 IP 주소가 할당되어 있다.

    • 클러스터 초기화: redis-cluster-init 서비스는 클러스터를 초기화하는 데 사용한다. 이 서비스는 모든 마스터와 슬레이브 노드가 시작된 후에 실행되며, redis-cli --cluster create 명령을 사용하여 클러스터를 구성한다.

    • 볼륨: 각 Redis 노드는 데이터를 저장하기 위해 독립적인 볼륨을 사용한다. 이를 통해 컨테이너가 재시작되어도 데이터가 유지된다.

    • 브리지 네트워크: 사용자 정의 브리지 네트워크 (redis-net )가 설정되어 있으며, 이를 통해 컨테이너 간의 격리와 네트워킹이 관리된다.

    • Redis 클러스터를 효율적으로 관리하고 운영할 수 있게 해주며, Docker Compose를 사용함으로써 여러 컨테이너를 쉽게 설정하고 관리할 수 있다.

  2. docker-compose 명령어 입력

    # 실행 docker-compose up # 백그라운드에서 실행 docker-compose up -d # 서비스 중지 docker-compose stop # 서비스 다운 docker-compose down # 실행중인 서비스 확인하기 docker-compose ps # 서비스 로그 확인하기 docker-compose logs
    • 실행 확인

    • Image 20231129162831
    • 3개의 master와 3개의 slave 가 실행 된 걸 확인 할 수 있다.

캐모마일 프로젝트 적용

  1. dependency 등록(pom.xml)

    <dependency> <groupId>net.lotte.chamomile.module</groupId> <artifactId>chamomile-cache-redis</artifactId> </dependency>
  2. yaml 파일 설정

    chmm: cache: instance: redis #none/redis/hazelcast ## 아래 클러스터는 redis cluster 적용시에만 필요 mode: cluster redis-nodes: - 10.131.4.85:3002 - 10.131.4.85:3001 - 10.131.4.85:3000 redis-max-redirects: 6 host: 10.131.4.85
    • 클러스터 관련 설정은 클러스터 설정 진행시에만 작성한다.

    • mode : cluster -> 레디스 클러스터 진행시 적용 한다.

    • redis-nodes : 클러스터를 구성하는 Redis 노드 들의 주소와 포트 목록이다.

    • redis-max-redirects : 클라이언트가 올바른 노드에 도달할 때까지 리디렉션 되는 최대 횟수이다

    • host : Redis 클러스터에 연결하는 데 사용되는 public IP 주소 이다.

  3. 클러스터 관련 빈 커스터마이징 chamomile-cache-redis에서 클러스터로 redis connection factory빈을 생성하는 코드를 다음과 같이 선언하여 커스터마이징을 진행하면 된다.

    ChamomileCacheRedisCustomConfiguration.java

    public class ChamomileCacheRedisCustomConfiguration { @Bean @ConditionalOnProperty(prefix = "chmm.cache", name = "mode", havingValue = "cluster") public RedisConnectionFactory redisConnectionFactory() { // Redis 클러스터 구성을 설정합니다. RedisClusterConfiguration redisClusterConfiguration = new RedisClusterConfiguration(chamomileCacheProperties.getRedisNodes()); redisClusterConfiguration.setMaxRedirects(chamomileCacheProperties.getRedisMaxRedirects()); // 클러스터의 노드의 상태 변경을 감지하고 처리하기 위한 리프레시 옵션을 설정합니다. // 이 옵션은 클러스터의 노드의 상태 변경되었을 때 자동으로 갱신되도록 합니다. ClusterTopologyRefreshOptions clusterTopologyRefreshOptions = ClusterTopologyRefreshOptions.builder() .enableAllAdaptiveRefreshTriggers() .enablePeriodicRefresh(Duration.ofHours(1L)) .build(); // 클라이언트 옵션을 설정합니다. 위에서 정의한 토폴로지 리프레시 옵션을 포함합니다. ClientOptions clientOptions = ClusterClientOptions.builder() .topologyRefreshOptions(clusterTopologyRefreshOptions) .build(); // 클러스터 컨테이너에 내부 DNS 설정을 무시하고, // 사용자 정의 매핑을 제공합니다. MappingSocketAddressResolver resolver = MappingSocketAddressResolver.create(DnsResolvers.UNRESOLVED, hostAndPort -> { return HostAndPort.of(chamomileCacheProperties.getHost(), hostAndPort.getPort()); }); // Lettuce 클라이언트에 사용될 리소스를 설정합니다. // 여기에는 위에서 정의한 주소 해석 로직(resolver)가 포함됩니다. ClientResources clientResources = ClientResources.builder() .socketAddressResolver(resolver) .build(); // Lettuce 클라이언트 구성을 설정합니다. // 이 구성에는 명령 타임아웃, 클라이언트 옵션, 클라이언트 리소스 및 읽기 선호도가 포함됩니다. LettuceClientConfiguration clientConfiguration = LettuceClientConfiguration.builder() .commandTimeout(Duration.of(10, ChronoUnit.SECONDS)) .clientOptions(clientOptions) .clientResources(clientResources) .readFrom(ReadFrom.REPLICA_PREFERRED) .build(); return new LettuceConnectionFactory(redisClusterConfiguration, clientConfiguration); } }
Last modified: 10 1월 2025