1223v

Redis 데이터 분산 [redis 죽으면 어카노…?] 본문

개발/개발 고찰

Redis 데이터 분산 [redis 죽으면 어카노…?]

1223v 2025. 2. 5. 19:46

고민의 시작


  • 우리 프로젝트는 MYSQL RT 저장 방식 ⇒ Redis RT 저장 방식으로 변경했다.
  • 그렇다면 고려해야하는 것이 redis가 다운되었을 경우의 복구 전략이다..

왜 이 고민이 필요해?


  • 현재 redis를 도입하는 대부분의 프로젝트들이 로그인에서 RT를 저장하는 부분일 것이다.

사용자 ⇒ 로그인 시도 ⇒ at/rt 발급 ⇒ rt redis에 저장 ⇒ at/rt 반환 ⇒ 로그인 성공

보통 토큰을 사용한 로그인은 위와 같은 과정을 따르는데,

사용자 ⇒ 로그인 시도 ⇒ at/rt 발급 ⇒

rt redis에 저장

at/rt 반환 ⇒ 로그인 성공

redis가 다운된다면 다음 과정마저, 에러가 나서 모든 로그인 과정이 불통이 된다.

이는 로그인이라는 도메인이 redis에 강한 연결(의존)이 되있음을 의미한다.

때문에 우리는 이 강한 의존도를 분리해줄 필요가 있다.

 

 

 

기존 방식


  • redis가 도입되면서, 따로 redis 관련 에러 처리를 해주지 않았다.

 

 

변경 방식


이후, redis에 어떠한 복구 전략이 없다는 부분에서 찾아보고 도입하게 되었다.

우선 생각한 해결 방식은 아래와 같다.

  1. Fallback 전략Redis가 다운된 경우: 예외 처리 후 MySQL member 테이블에 RT를 저장하여 사용.
  2. RT 갱신 시: Redis가 복구되면 다시 Redis를 우선적으로 사용하도록 설정.
  3. Redis가 정상 작동할 경우: Redis에 RT를 저장하고, AT 검증 시 사용.
  4. Redis Master/Slave (Replication)
  5. Redis Cluster

우리는 오늘 Redis에서 제공하는 Redis Master/Slave (Replication)Redis Cluster를 알아보도록 하겠다

 

 

 

 

Redis Master/Slave (Replication)


Master 노드가 데이터를 저장하고 Slave 노드가 Master의 데이터를 복제하여 백업 역할을 한다.

  • 주로 고가용성을 위해 사용한다.
  • Redis Sentinel을 추가하면 자동 장애 조치를 지원할 수 있다.
  • 하나의 Master에 다수의 Slave가 붙을 수 있다.
  • Master는 Read-Write Mode로 동작하고, Slave는 Read-Only Mode로 동작한다.
  • Master와 Slave 사잉의 Replication은 Async 방식을 이용

Data 변경시 변경 내용을 backlog에 기록 ⇒ Slave가 Master에 접속하여 backlog의 내용을 바탕으로 Replication 수행

이 과정에서 비동기로 동작하므로서 Master의 저장된 Data가 Slave에 잠깐동안 저장되지 않을 수 있음.

예). npm 버전 업데이트시 어쩌다 한번 검색창에서의 버전과 라이브러리 페이지 내에서의 버전 차이가 보여짐

중요.

Master가 죽을 경우 Slave는 Master에게 주기적으로 Connection을 요청하며 Master가 되살아 날때까지 대기 ⇒ Master가 복구되면 Slave는 Replication을 수행하여 master와 동기화

만약 Master 복구가 힘든 경우 Redis 관리자는 Slave 중에 하나를 수동으로 Master로 승격 → 나머지 Slave들을 새로운 Master로부터 Replication하도록 설정 → Master가 바뀐뒤에는 죽었던 Master는 새로운 master의 Slave로 설정

Sentinel

  • Master의 동작이 멈출경우, Redis 클라이언트는 Slave를 통해서 읽기 수행은 가능하지만, 쓰기 동작은 불가능하다.Master의 DownTime은 Redis Cluster의 가용성을 떨어뜨린다.
  • result.

⇒ 이 문제를 해결하는 것이 Sentinel이다.

  • Sentinel은 Master가 죽는지 감지하고 Master가 죽었을 경우 Slave 중 하나를 Master로 승격시키고 기존의 Master는 Slave로 강등시킨다.
  • Redis 관리자 없이 자동으로 동작하기 때문에 Master의 Downtime을 최소화하여 HA를 가능하게 만들 수 있다.

 

 

1) Redis Sentinel 설정 (sentinel.conf)


sentinel monitor mymaster 127.0.0.1 6379 2
sentinel down-after-milliseconds mymaster 5000
sentinel failover-timeout mymaster 60000
sentinel parallel-syncs mymaster 1

2) Spring Boot에서 Redis Sentinel 설정 (application.yml)

spring:
  redis:
    sentinel:
      master: mymaster
      nodes: 192.168.1.10:26379,192.168.1.11:26379,192.168.1.12:26379

 

 

Sentinel의 Split-brain 방지 방법

1) Sentinel 홀수 개 배치 (Quorum 투표) = 일반적인 방법

  • Sentinel을 3개 5개 처럼 홀수 개로 배치하여 과반수를 확보
  • 투표로 가장 많은 Sentinel이 인식한 노드를 마스터로 지정
  • 설정 값 적용 가능 ⇒ 특정 Redis에 장애 발생 시 몇개의 Sentinel이 특정 Redis의 장애 발생을 감지시 장애라 판단

✅ 2) STONITH

  • 문제가 있는 노드를 강제로 종료하여 중복 마스터 방지
  • 고가용성 클러스터 환경에서 주로 사용

✅ 3) Network Partition Detection (네트워크 분리 감지)

  • 클러스터의 네트워크 상태를 주기적으로 체크하여 마스터 승격 전 네트워크 상태를 검증

 

 

HAProxy

  • Redis Master-Slave 구성 시 Client는 각각의 IP/Port를 알고 적절하게 붙어서 동작 수행
  • BUT, Master가 교체될 때 마다 Redis를 이용하는 모든 Client의 설정을 바꾸는 일은 쉬운게 아님.
  • HAProxy가 client에게 redis의 Master, Slave에 일정하게 접근할 수 있는 End-point를 제공
  • tcp-check를 이용해서 주기적으로 각각 어떤식으로 동작하는 파악하고 그에 따라 동적으로 Routing Rule을 설정

 

 

 

Redis Cluster


여러개의 redis 노드를 사용하여 데이터를 자동으로 Replication 및 샤딩(분산 저장) 기법

  • 수평 확장 지원 ⇒ 하나의 마스터가 모든 데이터를 저장하는 기존 방식과 달리 데이터를 여러 마스터 노드에 분산하여 저장
  • 고가용성 ⇒ 특정 노드가 장애가 나도 자동으로 복구(Failover)
  • 자동 페일오버 ⇒ 마스터가 죽으면 슬레이브가 자동으로 승격되어 서비스 중단 방지
  • Split-brain 방지 ⇒ 홀수 개로 구성하여 잘못된 마스터 승격 방지
  • 각 redis 모두 직접 연결하여 gossip Protocol을 통해 통신(상태 정보 교환)
  • [master의 죽음을 파악한 뒤 스스로 master로 승격하여 master를 대신함]
  • gossip Protocol은 Redis 클라이언트가 이용하는 port 번호보다 높은 번호 사용 (기본 : 6379)
  • client도 redis와 직접 연결
  • Redis Cluster는 Muti-master, Muti-Slave 구조

중요!

  • Slave Redis에게 쓰기 요청을 보내면 Slave Redis는 해당 요청을 처리할 수 있는 Master Redis의 정보를 Client에게 넘겨준다
  • 요청 Redirection으로 인해 Client는 Redis Cluster 이용시 redis Cluster를 지원하는 라이브러리가 필수 (spring data redis와 같은 라이브러리)
  • Master와 Slave사이의 Replication은 비동기방식 ⇒ Master 다운은 Master-Slave 간의 Data 정합성을 깰 수 있음. (데이터 충돌 발생시 무조건 나중에 Master가 된 Data를 기준으로 정합성 맞춤)

 

 

 

 

평가


고려 요소 Redis Sentinel Redis Cluster
데이터 정합성 ✅ 보장됨 (마스터-슬레이브 동기화) ❌ 보장되지 않음 (샤딩 중 일부 데이터 유실 가능)
수평 확장(Sharding) ❌ 지원 안함 (단일 마스터) ✅ 지원 (데이터 분산)
자동 페일오버 ✅ 지원 ✅ 지원
멀티 키 연산 ✅ 지원 (MGET, MSET 가능) ❌ 제한됨 (같은 슬롯에서만 가능)
설정 복잡도 🔻 단순함 🔺 복잡함
사용 사례 Refresh Token, 세션 저장, 인증 데이터 대규모 데이터 처리, 캐싱, 로그 저장

📢 Refresh Token 저장에서는 "데이터 유실 방지"와 "정합성 유지"가 중요하므로, Redis Sentinel이 더 적합함.

 

 

 

고찰


  • 우리는 결국 redis에 사용자의 정보를 저장하는 셈이다. 즉, redis가 다운되더라도 혹은 복구되더라도 충돌과 같은 장애는 막아야한다.
  • 또한, refreshtoken을 마이그레이션 하면서 관리포인트가 증가 했기때문에 더이상의 관리포인트를 늘리는 클러스터는 지양하고자 했다.
  • 때문에 현재 서비스에서 가장 적합한 복구 솔루션은 redis sentinel을 통한 복구 전략을 진행하는 것이 현재로써는 맞다고 생각한다.
    • 다른 이견 있으면 알려주세영
728x90