장난감 연구소

[캐시] 캐시 문제 해결 가이드 본문

개발/DB

[캐시] 캐시 문제 해결 가이드

changi1122 2025. 8. 26. 20:27

    캐시 관련 문제 방지 방법

    이런 문제가 있는지 알게 되어 나중에 알아보기 위해 저장해놓습니다.

     

    캐시 문제 해결 가이드 - DB 과부하 방지 실전 팁

    대용량 트래픽 환경에서 캐시를 사용할 때 주의해야할 위험 상황과 예방법을 소개합니다.

    toss.tech

     

    GPT 응답

    더보기

    캐시 스탬피드(Cache Stampede)란?

    캐시 스탬피드는 특정 캐시 키가 만료되었을 때 다수의 클라이언트 요청이 동시에 원본 데이터 소스(DB 등)에 몰리며 과부하가 발생하는 현상을 말합니다.

    예시 상황:

    1. 인기 있는 데이터(예: 실시간 뉴스 헤드라인)가 캐시에 저장됨.
    2. 캐시 만료 시간(TTL)이 되어 해당 키가 캐시에서 사라짐.
    3. 동시에 수천, 수만 개의 요청이 들어오면, 전부 DB로 향하게 됨.
    4. DB 과부하 → 응답 지연 또는 장애 발생.

    이게 바로 캐시 스탬피드 문제예요.


    발생 원인

    1. 동시에 요청이 몰리는 핫 키(Hot Key) 존재
    2. TTL(만료 시간)이 동일하게 설정되어 만료 순간에 요청이 집중됨
    3. 백업 캐시 전략 없음 (캐시 미스 시 바로 DB 접근)

    방지 방법

    캐시 스탬피드를 막기 위해 여러 기법이 사용됩니다:

    1. 캐시 만료 시간(TTL) 분산

    • 모든 키에 같은 TTL을 주지 않고, **랜덤 지연(randomized expiration)**을 추가해서 한꺼번에 만료되지 않도록 함.
    • int ttl = 60; // 60초 int jitter = new Random().nextInt(10); // 0~9초 랜덤 cache.set(key, value, ttl + jitter);
    • 이렇게 하면 특정 시점에 몰리는 현상이 줄어듦.

    2. 소프트 만료(Soft Expiration) / 백그라운드 갱신

    • 캐시 만료 전 일정 기간을 "소프트 만료"로 두고,
    • 첫 번째 요청자가 백그라운드에서 DB 갱신을 하도록 하고,
    • 다른 요청자들은 이전 캐시 값을 계속 사용하게 하는 방식.
      • 예: Guava Cache, Spring Cache에서 지원 가능.

    3. 뮤텍스(Mutex) / 락(Lock) 사용

    • 캐시에 값이 없을 때, 하나의 요청만 DB 조회하도록 락을 걸고, 다른 요청자는 기다리게 함.
    • Redis SETNX(set if not exists) 같은 기능을 활용.
      • 첫 번째 요청만 DB 조회 → 캐시에 반영
      • 이후 요청은 캐시된 값 사용

    4. Lazy Recalculation / 요청 직전 재계산

    • 요청이 들어왔을 때 캐시가 만료됐다면,
      • 만료 직후 DB에서 읽어오지 않고,
      • 미리 준비된 값(backup cache, stale cache) 을 반환
      • 동시에 백그라운드에서 새 값을 갱신

    5. 캐시 프리로딩(Cache Warming)

    • 캐시 만료 전에 미리 갱신해 놓는 방법.
    • 배치 작업이나 백그라운드 스케줄러(Cron)로 자주 조회되는 데이터를 캐시에 주기적으로 넣음.