민스씨의 일취일장

프로젝트 LOG | Redis를 클러스터로 만들어 분산캐시 도입하기 본문

Projects/MetaPay

프로젝트 LOG | Redis를 클러스터로 만들어 분산캐시 도입하기

읻민스 2024. 9. 15. 23:51
반응형

PaymentService에 적용된 Redis Cache를 분산 캐시(distributed cache)로 전환하는 과정(GitHub Issues #28)에 대한 글이다.

Redis를 클러스터로 만들어 분산캐시 도입하기

Redis Cluster로 분산 캐시 도입하기 썸네일 이미지이다.
Redis Cluster로 분산 캐시 도입하기

작업 순서 계획

1. redis.conf 작성 및 적용
2. 새로운 Redis용 인스턴스 생성
3. Redis 노드(컨테이너)들을 클러스터 구성(생성) 명령 수행
4. Redis 분산 캐시를 사용할 수 있도록 애플리케이션 설정 수정

1. redis.conf 작성 및 적용

nginx.conf와 마찬가지로, redis.conf를 작성해준다. 이 파일은 Redis 컨테이너 실행시 Volume으로 연결 해 줄 것이다. 경로는 어디다 해도 상관 없지만 민스씨 본인은 redis/redis.conf 경로로 할 것이다.

port 7000  # 각 노드마다 다른 포트 사용
cluster-enabled yes
cluster-config-file nodes.conf
cluster-node-timeout 5000
appendonly yes

해당 redis.conf를 컨테이너 내에서 참조할 수 있도록 volume mount해주면 컨테이너를 다시 실행해준다.

docker run -d -p 7000:7000 -p 17000:17000 \
-v /home/ec2-user/redis/redis.conf:/usr/local/etc/redis/redis.conf \
-d --name redis-cache redis \
redis-server /usr/local/etc/redis/redis.conf

2. 새로운 Redis용 인스턴스 생성

위의 1번 작업을 Redis 클러스터로 사용할 노드 인스턴스에서도 해준다. 레디스는 클러스터 구성을 위해 최소 3개의 노드를 필요로 하기 때문에 총 5개의 노드를 추가로 생성해 줄 것이다. 왜냐하면 3개의 노드와 노드 수만큼의 복제 노드(replicas=1)가 필요하기 때문이다. 좀 더 높은 수준의 가용성을 위해선 노드 수 또는 레플리카(복제 노드) 수를 늘리주면 된다.

인스턴스 생성 완료 메시지 모습이다.
인스턴스 생성 완료 메시지

🤓 AMI만 하나 잘 만들어 둬도, 인스턴스 생성은 정말 10초도 안걸린다. IaC까지 사용하면 어떨지 궁금하다.

레디스 컨테이너 생성 완료 모습이다.
Redis 컨테이너 생성

3. Redis 노드들을 클러스터로 구성(생성) 명령 수행

Redis 컨테이너들 중 하나, 아무곳에서나 shell에 접속한다.

docker exec -it [container_name] sh

그다음 클러스터 생성 명령어를 입력해준다.

redis-cli --cluster create \
PrivateIP_Instance1:7000 PrivateIP_Instance2:7001 \
PrivateIP_Instance3:7002 PrivateIP_Instance4:7003 \
PrivateIP_Instance5:7004 PrivateIP_Instance6:7005 \
--cluster-replicas 1

여기서 주의사항이 있다.

🚨 주의사항
1. cluster 연결시 사용할 포트들을 보안 그룹에서 모두 열어줘야 한다! 이부분을 또 까먹어서 원인파악에 시간이 들었다.
2. 또한, 해당 포트들에 각각 10000을 더한 17000-17005 범위 포트도 열어줘야 한다. 이는 클러스터 버스용으로 사용되는 포트들이다.

Redis가 성공적으로 clustered 된 모습이다.
Redis Clustered

4.  Redis 분산 캐시를 사용할 수 있도록 애플리케이션 설정 수정

application-redis.properties 수정
spring.data.redis.cluster.nodes=PrivateIP_Instance1:7000,PrivateIP_Instance2:7001,PrivateIP_Instance3:7002,PrivateIP_Instance4:7003,PrivateIP_Instance5:7004,PrivateIP_Instance6:7005
spring.data.redis.cluster.max-redirects=3
build.gradle 의존성 추가
implementation 'io.lettuce:lettuce-core'
RedisConfig에 redisConnectionFactory() 메서드 추가
@Bean
public RedisConnectionFactory redisConnectionFactory() {
    RedisClusterConfiguration clusterConfiguration = new RedisClusterConfiguration(
        Arrays.asList("PrivateIP_Instance1:7000", "PrivateIP_Instance2:7001", "PrivateIP_Instance3:7002",
                      "PrivateIP_Instance4:7003", "PrivateIP_Instance5:7004", "PrivateIP_Instance6:7005")
    );
    LettuceClientConfiguration clientConfig = LettuceClientConfiguration.builder()
    .commandTimeout(Duration.ofMillis(5000))
    .shutdownTimeout(Duration.ofSeconds(2))
    .build();
    return new LettuceConnectionFactory(clusterConfiguration, clientConfig);
}
여기서 사용하는 IP는 모두 Private IP이기 때문에, 로컬에서는 테스트하기가 어려웠다. 바로 도커 이미지로 푸시하고 EC2 환경에서 테스트를 진행해야 했다.

한 번에 바로 성공된건 아니지만, 성공! 서비스가 컨테이너에서 초기화 완료된 뒤 첫 GET 요청을 받으면 Redis 클러스터와 연결이 잘 됐다면 아래와 같은 메시지를 확인할 수 있다.

Redis Cluster 연결 메시지 모습이다.
Redis Cluster 연결 메시지

메시지가 굉장히 길고, Redis 컨테이너의 수 만큼 반복된다.

🚨 주의
메시지가 안 보일 때는 로그 레벨을 DEBUG로 설정해 보는 걸 추천한다. 

 

728x90
반응형