Architecture

캐시 스탬피드(Cache Stampede) 개념과 해결 방법

TedDev 2024. 11. 28. 17:17
728x90

캐시 스탬피드(Cache Stampede)는 캐시된 데이터가 만료될 때 다수의 클라이언트가 동시에 동일한 데이터를 요청하는 현상을 말한다. 이로 인해 원본 데이터 소스(예: 데이터베이스나 API)에 과부하가 발생하며 시스템 성능이 급격히 저하되거나 심지어 장애가 발생할 수 있다.

 

현상의 원인

  1. 캐시 만료 시점 동시 요청
    • 동일한 데이터를 요청하는 여러 클라이언트가 캐시된 데이터가 만료된 직후 동시에 원본 데이터 소스에 접근하려고 시도한다.
    • 예를 들어, 인기 있는 웹 페이지의 캐시가 만료되면 그 페이지를 요청하는 수많은 사용자의 요청이 한꺼번에 데이터베이스로 전달될 수 있다.
  2. 원본 데이터 소스의 처리 한계
    • 데이터베이스, API, 파일 시스템 등 원본 데이터 소스는 높은 동시 요청을 처리할 수 있는 용량에 한계가 있다.
    • 평소에는 캐시로 인해 부하가 분산되지만 캐시 스탬피드 상황에서는 병목현상이 발생할 수 있다.

 

문제가 발생하는 사례

  1. 대형 이벤트
    • 대규모 트래픽이 집중되는 이벤트 중 인기 콘텐츠의 캐시가 만료되면 동시다발적으로 캐시가 재생성되면서 서버 부하가 급격히 증가한다.
  2. 실시간 API 요청
    • 실시간 데이터를 캐시로 제공하는 서비스에서 캐시 갱신 주기가 짧거나 갱신 시점이 동시에 몰리면 문제가 발생한다.

 

해결 방법

1. 락(Locking) 사용

  • 설명 : 캐시가 만료되었을 때 여러 요청 중 하나의 요청만 데이터 갱신 작업을 수행하도록 제어한다.
  • 방법 : 분산 락 시스템(Redis의 SETNX 명령 등)을 사용해 캐시에 대한 갱신 권한을 단일 프로세스에 할당한다. 나머지 요청은 락이 해제되기를 기다리거나 캐시된 오래된 데이터를 임시로 반환한다.
  • 예시 코드 : Redis에서 락 사용
if redis.setnx("cache_lock:key", "lock_value"):
    # 데이터 갱신 작업 수행
    data = fetch_from_database()
    cache.set("key", data)
    redis.delete("cache_lock:key")
else:
    # 락 해제를 기다리거나 오래된 캐시 반환

 

 

2. 확률적 조기 만료 (Probabilistic Early Expiration, PER)

  • 설명 : 캐시가 만료되기 전에 일부 요청이 확률적으로 캐시를 갱신하도록 유도한다. 이를 통해 캐시 갱신 시점을 분산시킨다.
  • 방법 : 캐시 만료 시간과 실제 갱신 시간을 확률 기반으로 조정한다.
  • 장점 : 트래픽 분산 및 캐시 스탬피드 예방

 

3. 지터(Jitter) 적용

  • 설명 : 캐시 만료 시간을 고정하지 않고 무작위로 분산하여 특정 시점에 요청이 몰리지 않도록 한다.
  • 방법 : 캐시 만료 시간을 설정할 때 일정 범위의 랜덤 값을 더하거나 뺀다.
  • 예시
cache_expiry_time = 3600 + random.randint(-300, 300)  # ±5분

 

 

4. 캐시 레이어 계층화

  • 설명 : 캐시를 여러 계층으로 구성하여 최종 원본 데이터 소스에 대한 부하를 최소화한다.
  • 방법
    1. 애플리케이션 내부에서 로컬 메모리 캐시 사용
    2. 다양한 유형의 외부 분산 캐시와 조합
    3. CDN(Content Delivery Network)과 같은 글로벌 캐시 계층 추가

 

5. 백그라운드 캐싱 (Background Refresh)

  • 설명 : 캐시 만료 후 클라이언트 요청이 발생하기 전에 백그라운드 작업으로 미리 캐시를 갱신한다.
  • 방법 : 만료된 캐시를 주기적으로 갱신하는 백그라운드 프로세스를 추가한다.

예시 시나리오

웹 서비스

  1. 인기 뉴스 페이지 캐시 만료 → 동시 수백 개 요청 → 데이터베이스 과부하.
  2. 캐시 스탬피드 방지
    • 락을 사용해 하나의 요청만 데이터베이스로 접근
    • 나머지 요청은 갱신 완료 시 캐시된 데이터를 받음

API 호출

  1. 실시간 데이터를 캐싱하는 API에서 짧은 갱신 주기 → 갱신 시점에 요청 몰림
  2. 캐시 스탬피드 방지
    • 지터를 적용해 갱신 주기를 분산
    • 확률적 조기 만료로 갱신 시점을 동적으로 설정

 

결론

캐시 스탬피드는 고성능 시스템에서 빈번하게 발생할 수 있는 문제지만 락, 확률적 조기 만료, 지터, 백그라운드 캐싱 등 다양한 기술을 조합해 해결할 수 있다. 적절한 해결 방법을 선택하면 캐시 사용의 효율성을 극대화하고 시스템 안정성을 유지할 수 있다.

반응형

'Architecture' 카테고리의 다른 글

API 게이트웨이 패턴이란?  (2) 2024.12.20
Service Discovery  (1) 2024.12.06
트랜잭셔널 메시징  (0) 2024.11.26
Layered Architecture (계층형 아키텍처)  (0) 2024.06.20
스트랭글러 패턴 이란  (0) 2023.11.05