[Redis] Cluster Topology 설정

이재민·2024년 4월 25일
0

트러블슈팅&개선

목록 보기
1/5

Topology

토폴로지란, 컴퓨터 네트워크의 요소들(링크, 노드 등)을 물리적으로 연결해 놓은 것이다.

이슈 발생

재직중인 회사의 서비스에서 Redis Cluster 구조로 사용중이다.
AWS측에서 ElasticCache Cluster update 메일을 받았다.(필자는 받지 못하였고 이슈 발생 후 공유 받았다...)

안내 받은 날짜에 Redis Cluster가 업데이트되면서 토폴로지 정보가 변경되었고, 변경된 토폴로지 정보를 연결하지 못하면서 이슈가 발생하였다.
이슈 발생으로 인해 대략 수분간의 서비스 장애가 발생하였고, 서버 재기동을 통해 다시 node 정보를 찾도록 하여 1차 대응을 하였다.

주의사항

Lettuce RedisCluster를 사용할 경우 클러스터 토폴로지 정보를 주기적으로 가져와 업데이트 해야 한다.
노드가 추가/삭제/다운으로 인한 역할 변경(master -> replica) 등 클러스터 토폴로지 정보가 변경되었을 경우 최신 정보로 업데이트 해야 한다.
그렇지 않을 경우 서비스 전면 장애가 발생할 수 있다.

출처: [이동욱님 블로그](https://jojoldu.tistory.com/418)

ClusterTopology 설정

List<String> nodes = Collections.singletonList(redisProperties.getClusterEndPoint());
            RedisClusterConfiguration configuration = new RedisClusterConfiguration(nodes);

            // topology refresh option
            ClusterTopologyRefreshOptions topologyRefreshOptions = ClusterTopologyRefreshOptions.builder()
                .dynamicRefreshSources(true) 
                .enablePeriodicRefresh(Duration.ofSeconds(60)) 
                .enableAllAdaptiveRefreshTriggers()
                .adaptiveRefreshTriggersTimeout(Duration.ofSeconds(30))
                .build();

            // clusterClientOptions
            ClusterClientOptions clientOptions = ClusterClientOptions.builder()
                .autoReconnect(true)
                .topologyRefreshOptions(topologyRefreshOptions)
                .build();

            LettuceClientConfiguration clientConfig = LettuceClientConfiguration
                .builder()
                .clientOptions(clientOptions)
                .readFrom(ReadFrom.REPLICA_PREFERRED)
                .build();

            return new LettuceConnectionFactory(configuration, clientConfig);

ClusterTopologyRefreshOptions

  • dynamicRefreshSources: (default: true)
    • 새로고침시 발견된 모든 노드로부터 클러스터 토폴로지 정보를 얻어올 수 있다. false로 설정하면 초기 seed 노드에서만 클러스터 토폴로지 정보를 얻어온다.
  • enablePeriodicRefresh: (default: false)
    • 주기적으로 클러스터 토폴로지 새로고침 활성화, 비활성화에 대한 설정이다. 활성화시 백그라운드에서 주기적으로 토폴로지 정보를 새로고침하여 얻어온다. 해당 주기를 설정하면 refreshPeriod 속성에 설정되어 정해진 주기로 동작하게 된다.
  • enableAllAdaptiveRefreshTriggers: default: none,
    • 기본값으로는 사용하지 않음이다. 해당 설정은 선택적으로 적응형 토폴로지 새로고침 트리거를 활성화할지의 여부다. 말이 어려우니 자세히 풀어보면 해당 값을 설정할 경우 RefreshTrigger에 정의된 모든 enum으로 설정된 모든 refresh 이벤트에 대해 토폴로지 갱신을 실행한다. 예를 들어 MOVED, ACK 등 이벤트가 발생할마다 토폴로지를 갱신하는건데, 이벤트가 많이 발생하는 경우에는 성능적으로 이슈가 발생할 수도 있다.
  • adaptiveRefreshTriggersTimeout: default: 30s
    • enableAllAdaptiveRefreshTriggers 설정의 타임아웃을 설정하는 것이다. 타임아웃 내 트리거는 무시되고, 첫 번째로 활성화된 트리거만이 토폴로지 새로고침을 유발하게 된다.

ClusterClientOptions

  • autoReconnect: default: true
    • 클러스터 노드와의 연결이 끊어진 경우 자동으로 재연결을 시도할지 여부를 설정한다.

Lettuce에서 Redis Cluster 재접속 과정

클러스터는 클러스터 내 노드들의 IP, Port를 지정해서 접속을 한다. Redis Cluster의 노드들이 바뀌면 도메인에 설정된 서버의 IP도 바뀌게 된다. autoReconnect를 사용할 경우 도메인을 다시 쿼리하므로 새로운 서버로 접속이 가능하다.
Lettuce에서는 ConnectionWatchdog를 생성하여 connection을 진행하게 되는데, 이러한 과정도 ClusterClientOption을 통해 진행한다.
reconnect0에서 실제 접속을 시도한다. 이때, 재접속의 주소는 SocketAddress이다. SocketAddress는 이미 DNS 쿼리 후에 도메인이 IP로 변환된 값을 가지고 있다.

ConnectionWatchdog는 ConnectionBuilder에서 ClientOptions 중 AutoReconnect 설정이 되어있을때만 생성된다. 그래서 AutoReconnect 설정을 하지 않는다면, ConnectionWatchdog에서는 이미 주소를 Resolve한 SocketAddress를 이용하므로 변경된 IP를 찾지 못한다.

맺음말

Lettuce Redis Cluster를 사용중이라면 반드시 ClusterTopology 설정을 진행해야한다.
고가용성을 확보하기 위해 Redis Cluster를 이용하였는데, ClusterTopology 설정을 하지 않아 서비스 장애가 발생할 수 있으니 주의해야한다.

참고
https://lettuce.io/core/release/api/io/lettuce/core/cluster/ClusterTopologyRefreshOptions.html
https://lettuce.io/core/5.3.7.RELEASE/reference/index.html#redis-cluster.client-options
http://redisgate.kr/redis/clients/lettuce_cluster.php

profile
문제 해결과 개선 과제를 수행하며 성장을 추구하는 것을 좋아합니다.

0개의 댓글