k8s_redis_sentinel_java_app_2
쿠버네티스 환경에서 Redis-Sentinel Java App 구축 ②
Failover 테스트
🖧 Redis-Sentinel 파드 다이어그램: Redis-0 Master
1. Failover(장애조치) 테스트 시작
SSH 터미널을 2개 열어서, Terminal-1에서는 App 파드 생성, 레디스 파드 다운 등을 실행하고, Ternimal-2에서 App 로그를 본다.
Java(Spring) App 파드 생성
서버 (Terminal-1 [~/kube/app/sentinel])에서 실행
$ kubectl apply -f app-deployment.yaml -> 파드 생성
💻 App 로그
서버 (Terminal-2 [~/kube/app/sentinel])에서 실행
$ kubectl logs -f -l app=spring-redis-sentinel-app
1초개 10개씩 입력([SUCCESS])되는 것을 확인할 수 있다.
💥 1. 레디스(Redis-0) 파드 다운
Ternimal-1) $ date; kubectl delete pod redis-0 -> 15:47:39
💻 Redis-0 LOG
① 39초 레디스 다운 (+0초)
② 41초 레디스 재시작 (+2초)
③ 54초 마스터 -> 복제로 전환 (+15초)
Redis-0 전체 로그
💻 Redis-1 LOG
① 43초 복제 -> 마스터로 전환 (+4초)
App 로그
Terminal-2) $ kubectl logs -f -l app=spring-redis-sentinel-app
① 39초 레디스 연결 끊김 -> 재연결 시도 (+0초)
② 44초 입력 실패 1개 발생: keyA-00000147 (+5초)
③ 45초 부터 입력 성공 (+6초)
App 전체 로그
🖧 Redis-Sentinel 파드 다이어그램: Failover 상태 (Redis-1 Master)
2. Failback(원상복구) 테스트
1) 레디스(Redis-1) 파드 💥다운(delete)
Terminal-1) $ date; kubectl delete pod redis-1 -> 15:48:05
💻 Redis-1 로그
① 05초 레디스 다운 (+0초)
② 08초 레디스 재시작 (+3초)
③ 20초 마스터 -> 복제로 전환 (+15초)
💻 Redis-0 로그
① 09초 복제 -> 마스터로 전환 (+4초)
💻 App 로그
① 06초 Redis-1 연결 끊김 -> 재접속 시도 (+1초)
② 10초 입력 성공(09초에 Redis-0가 마스터로 전환되었다) (+5초)
App 전체 로그
🖧 Redis-Sentinel 파드 다이어그램: 원상복구 상태 (Redis-0 Master)
🧑💻 테스트 검토 및 핵심 요약
이번 장애 조치(Failover/Failback) 테스트를 통해 쿠버네티스 환경의 Redis-Sentinel과 Java(Spring Boot) 애플리케이션 간의 실제 연동 동작을 검증했습니다.
⏱️ 장애 조치 타임라인 (Timeline)
| 구분 | 시각 (상대 시간) |
Redis-Sentinel 동작 | Java (Spring) App 동작 |
|---|---|---|---|
| 장애 발생 | 15:47:39 (+0초) |
Master(Redis-0) 파드 종료 (delete) | 연결 끊김 감지 및 재접속 시도 (Reconnecting) |
| Failover | 15:47:43 (+4초) |
Sentinel이 장애 감지 후 Redis-1을 Master로 승격 | Sentinel로부터 신규 Master IP 수신 |
| 복구 완료 | 15:47:45 (+6초) |
신규 Master(Redis-1) 데이터 쓰기 준비 완료 | [SUCCESS] 정상 쓰기 재개 (단 1개 요청 재시도 처리) |
| 구 마스터 재기동 | 15:47:54 (+15초) |
재시작된 Redis-0이 Redis-1의 Replica로 승격/연동 | 영향 없음 (정상 서비스 유지) |
💡 실무 적용을 위한 핵심 시사점 (Key Takeaways)
-
1. 센티널 Failover 전환 시간 (약 4~5초):
마스터 파드가 다운된 후 센티널이 다운을 판정(down-after-milliseconds 3000)하고, 투표(Quorum)를 거쳐 새로운 마스터를 승격시키기까지 약 4초의 다운타임이 발생합니다. -
2. Spring/Lettuce 클라이언트 재시도(Retry)의 중요성:
이번 테스트에서 데이터 유실이 거의 없었던 핵심 이유는 App 측의 재시도(Retry 5회 / 5초) 설정 덕분입니다. 마스터 전환 중 발생한 1개의 실패 요청(keyA-00000147)도 백그라운드 재시도를 통해 신규 마스터로 전달되어 무중단에 가까운 서비스 연속성을 확보했습니다. -
3. 사용자 경험(UX) 및 타임아웃 고려사항:
클라이언트 관점에서는 장애 발생 시 약 4~5초간의 응답 지연(Latency)이 발생합니다. 웹/앱 프론트엔드 API 호출 시 사용자 화면이 멈추지 않도록 Front-end Timeout 및 Circuit Breaker(Resilience4j 등)를 적절히 조합하는 것을 권장합니다. -
4. Automatic Failback(원상복구) 미지원 및 정상 동작 특성:
기존 Master(Redis-0)가 다시 살아나더라도 기존 Master 위치로 복구(Failback)되지 않고, 신규 Master(Redis-1)의 Replica로 들어가는 것이 Sentinel의 정상적인 동작 방식입니다. (테스트 2번의 Failback은 Redis-1을 강제로 지워 재유도한 결과입니다.)
🛡️ Front-end Timeout 및 Circuit Breaker 설명
🛡️ 레디스 장애 시 시스템 마비를 막는 안전장치
센티널의 장애 조치(Failover) 동안 발생하는 4~5초간의 응답 지연(Latency)은 백엔드 서버와 사용자 화면으로 장애가 전파되는 연쇄 장애(Cascading Failure)를 유발할 수 있습니다. 이를 방지하기 위해 실무에서는 다음 두 가지 안전장치를 반드시 결합하여 구축합니다.
1. Front-end Timeout (프론트엔드 타임아웃)
사용자 브라우저나 모바일 앱이 백엔드 API를 호출한 후 "응답이 오지 않을 때 무한정 대기하지 않고 요청을 포기하는 최대 시간"입니다.
- 문제 상황 (Timeout 미설정 시): 레디스 장애 동안 4초간 응답이 멈추면, 답답한 사용자가 '새로고침'이나 '버튼'을 연타합니다. 이로 인해 백엔드 Tomcat/Spring 쓰레드(Thread)가 고갈되어 웹 서버 전체가 다운됩니다.
- 해결 방안 (2~3초 Timeout 적용): 2초 내 응답이 없으면 즉시 요청을 중단하고 "일시적인 네트워크 지연입니다. 잠시 후 다시 시도해 주세요"라는 안내를 띄워 백엔드 폭주를 차단합니다.
2. Circuit Breaker (서킷 브레이커 - Resilience4j)
전기 배전반의 '차단기(두꺼비집)'처럼 백엔드(Spring) 애플리케이션 내부에 설치하여, 레디스 장애 감지 시 차단기를 열어(Open) 레디스로의 접속 시도를 즉시 중단시키는 라이브러리입니다.
- 🟢 CLOSED (정상): 모든 캐시/데이터 요청을 레디스로 정상 전달합니다.
- 🔴 OPEN (차단): 레디스 지연/에러율이 지정치를 넘으면 차단기를 열어 레디스 호출을 아예 시도조차 하지 않고, 미리 준비된 대체 로직(Fallback: 예: Main RDB 직접 조회)을 즉시 실행합니다.
- 🟡 HALF-OPEN (검증): 레디스가 복구되었는지 확인하기 위해 소수의 요청만 살짝 보내보고, 정상 동작이 확인되면 다시 🟢 CLOSED 상태로 복구합니다.
🔄 장애 발생 시 두 기술의 협업 프로세스
- 0초 (레디스 Master 다운): Sentinel이 Failover를 시작하며 응답 지연 발생
- 1~2초 (Circuit Breaker 작동): Spring App의 Resilience4j가 에러/지연을 감지하고 차단기를 🔴 OPEN으로 전환 ➔ 레디스 대신 RDB를 조회하거나 기본값 반환(Fallback)
- 2초 (Front-end Timeout 작동): 프론트엔드가 요청을 안전하게 끊어내어 무한 로딩 및 사용자 연타로 인한 WAS 폭주 방지
- 4~5초 (Failover 완료 & 자동 복구): Sentinel이 신규 Master 승격을 완료하면, Resilience4j가 이를 감지하여 🟢 CLOSED로 돌려놓고 캐시 서비스 자동 정상화
| << K8s Redis-Sentinel App ① | K8s Sidecar 패턴 준비 ① >> |
|---|
