⚠️ 캐시 스탬피드(Cache Stampede) 현상과 해결 전략

업데이트:
1 분 소요

🧨 캐시 스탬피드란?

캐시 스탬피드(Cache Stampede) 또는 Thundering Herd Problem
캐시 미스 시 다수의 요청이 동시에 원본 저장소(DB) 를 조회하여 병목이 발생하는 현상입니다.

alt

위 그림처럼 여러 사용자가 동시에 요청을 보내고, 해당 캐시 키가 만료되어 있는 경우,
모든 요청이 동시에 DB로 몰리는 현상이 발생합니다.
결과적으로 데이터베이스에 급격한 부하가 걸리고, 장애나 지연이 발생할 수 있습니다.


🧩 원인 정리

  • Cache Aside 전략 사용 중 캐시 미스
  • 캐시 TTL이 만료되거나 제거됨
  • 동시에 수많은 요청이 DB에 접근하여 적재

🔧 해결 방법

1️⃣ 잠금(Locking) 방식

  • 최초 1개의 요청만 DB에 접근하도록 하고, 나머지는 대기
  • 캐시 적재 후 나머지는 캐시에서 응답
  • Redis의 SETNX 또는 분산 락 활용 가능
if (redis.setnx(key + ":lock", "1")) {
   // DB 조회 및 캐시 적재
   redis.set(key, value, 60);
   redis.del(key + ":lock");
} else {
   // 대기 또는 fallback 처리
}

단점: 락 점유 실패, 데드락, 타임아웃 고려 필요


2️⃣ 외부 재계산(Background Refill)

  • 별도의 백그라운드 스레드나 크론 잡이 주기적으로 캐시를 갱신
  • 사용자 요청 시 캐시가 항상 존재할 확률이 높아짐
✔️ 장점: 사용자 요청이 DB에 직접 접근하는 일 없음  
❌ 단점: 사용되지 않는 데이터도 갱신 → 리소스 낭비

3️⃣ 확률적 조기 재계산 (Probabilistic Early Recompute)

  • TTL이 얼마 안 남았을 때 일부 요청만 캐시를 재적재
  • 캐시 만료 시간이 임박하면 확률적으로 갱신 시도
# 예시: 확률적 재적재 조건 (Python)
if (current_time > expire_time - threshold):
    if (random() < probability):
        refresh_cache()

➡️ 스탬피드 발생 가능성을 확률적으로 분산시킴


🔁 실무 적용 팁

  • TTL + 랜덤 편차 적용해 캐시 만료 시점 분산
  • Redis 기반 Lock 구현 시 Redisson, Lettuce 고려
  • 외부 재계산 방식은 유사 CDN, 검색 캐시에 적합
  • 가능하면 읽기 요청 분산을 위해 복제 DB 또는 CQRS 아키텍처도 활용

🧠 마무리 정리

전략 장점 단점
Locking 단일 요청만 DB 접근 락 관리 복잡
외부 재계산 안정적 응답 리소스 낭비 가능
확률적 재계산 실시간 대응 + 분산 TTL 조정, 튜닝 필요

태그: , , , , , , , ,

카테고리:

업데이트:

댓글남기기