# Redis Cache Avalanche: 눈사태처럼 쏟아지는 트래픽 막아내기
Table of Contents
금요일 오후 6시, 서버실의 악몽
대규모 트래픽을 처리하는 서비스에서 가장 무서운 시나리오는 바로 **“캐시가 꺼지는 순간”**입니다. 평소에 데이터베이스(DB) 앞단에서 수십만 TPS를 막아주던 Redis가 죽거나, 혹은 대량의 데이터가 동시에 만료된다면 어떻게 될까요? 그 막대한 트래픽은 고스란히 데이터베이스로 쏟아집니다. 마치 산꼭대기에서 굴러떨어진 작은 눈덩이 하나가 거대한 눈사태가 되어 마을을 덮치는 것처럼 말이죠.
이것이 바로 Cache Avalanche(캐시 눈사태) 현상입니다.
Cache Avalanche vs Cache Stampede
두 현상은 비슷해 보이지만 발생 원인과 양상이 다릅니다. 정확한 처방을 위해서는 이 둘을 명확히 구분해야 합니다.
1. Cache Avalanche (눈사태)
- 원인: 수많은 캐시 키(Key)들이 동시에 만료되거나, Redis 서버 자체가 장애로 인해 죽었을 때 발생합니다.
- 현상: 전체적인 트래픽이 일시에 DB로 쏠리며 DB 서버의 CPU와 메모리가 급증합니다.
- 예시: 서버 재시작 시점에
TTL = 1시간으로 모든 데이터를 캐싱했습니다. 정확히 1시간 뒤, 모든 데이터가 동시에 만료되면서 순간적으로 DB에 수천 배의 부하가 가해집니다.
2. Cache Stampede (우르르 몰려감)
- 원인: **“매우 인기 있는 키 하나”**가 만료되었을 때 발생합니다.
- 현상: 그 키를 조회하려는 수천 개의 요청이 동시에 “어? 캐시가 없네? 내가 DB에서 가져와야지”라고 판단하고 DB를 타격합니다. (Thundering Herd 문제와 유사합니다)
- 예시: 인기 가수의 콘서트 티켓 예매 페이지에서 좌석 정보(
seat_map) 캐시가 만료된 찰나의 순간.
어떻게 막을 수 있을까?
Avalanche 방지: “랜덤(Random)은 나의 친구”
모든 캐시의 만료 시간을 똑같이(예: 60분) 설정하는 것은 시한폭탄을 설치하는 것과 같습니다. 여기에 **Jitter(랜덤 값)**를 섞어주세요.
- 기본 TTL: 60분
- 실제 설정 TTL: 60분 +
Random(0 ~ 10분)
이렇게 설정하면 캐시 만료 시점이 10분에 걸쳐 고르게 분산되므로, DB가 숨 쉴 틈이 생깁니다. 물론, Redis 서버 자체를 고가용성(Cluster, Sentinel)으로 구성하여 서버 장애에 대비하는 것은 기본 중의 기본입니다.
Stampede 방지: “줄을 서시오”
인기 있는 키가 만료되었을 때, 너도나도 DB로 달려가게 두면 안 됩니다. **Mutex Lock(상호 배제 락)**을 사용하여 “가장 먼저 도착한 1명”만 DB에 보내고, 나머지는 기다리게 해야 합니다.
# 의사 코드 (Pseudo-code)
data = redis.get(key)
if not data:
# 락 획득 시도 (setnx: set if not exists)
if redis.setnx(lock_key, "locking"):
# 1등(락 획득 성공)만 여기를 실행
data = db.query(key)
redis.set(key, data)
redis.del(lock_key) # 락 해제
else:
# 나머지는 락이 풀릴 때까지 잠깐 대기 후 다시 캐시 조회
sleep(0.1)
data = redis.get(key)
또 다른 방법으로는 PER(Probabilistic Early Recomputation) 알고리즘이 있습니다. 만료 시간이 완전히 끝나기 전에, 트래픽이 많아지면 확률적으로 미리미리 캐시를 갱신해두는 스마트한 기법입니다.
마치며
캐시는 양날의 검과 같습니다. 잘 쓰면 성능이 폭발적으로 좋아지지만, 캐시에만 의존하다가 장애가 발생하면 시스템 전체가 마비되는 캐시 의존성(Cache Dependency) 문제가 생길 수 있습니다. 개발할 때 “캐시가 있으니까 DB는 괜찮겠지”라고 안일하게 생각하면 안 됩니다. **“캐시가 모두 날아갔을 때, 우리 DB가 이 트래픽을 견딜 수 있는가?”**를 항상 고민하고 테스트해야 합니다.
만약 DB가 견딜 수 없다면? Circuit Breaker를 도입하여 과도한 요청을 차단하거나, 랜덤 TTL과 락 전략으로 무장하여 최악의 상황을 대비해야 합니다. 준비된 시스템만이 눈사태 속에서도 살아남을 수 있습니다.