캐시된 Stampede 문제를 실제로 해결

7324 단어 Cache캐시

Cache Stampede


캐시 만료로 오리지널(데이터베이스 등)에 액세스하는 경우 부하가 증가하는 문제를 Cache Stampede라고 합니다.Stampede는 일본어로'몰려온다'는 의미의 단어다.
※ 그 외에도 캐시 미스 스톰, 선더링 허드, 독필 등 다양한 명칭이 있다.
이 글은 Cache Stampede 문제에 대한 대책으로memcached의 기능을 semafo로 사용하고origin에 대한 접근을 제어하는 방법을 기술하고 있다.
문제를 정리하기 위해 현금을 사용할 때의 전형적인 처리를 되돌아보면서 본다.

단순 캐시


캐시는 보통 유효기간이 있으며, 기한이 지나면 캐시를 사용하지 않고, 오리지널 (데이터베이스 등) 에 접근하여 새로운 결과를 얻어 캐시에 저장하고 응답을 되돌려줍니다.
실복으로 대략 아래와 같다.
# キャッシュからデータを取得する
data = get_cache(key)

if not data:
  # キャッシュがなければデータベースから取得する
  data = get_data_from_database(...)

  # 新しいデータをキャッシュに保存する
  set_cache(key, data, ttl=60)

# ユーザーにレスポンスを返す
send_response(data)

방문량이 적은 경우


방문자가 적으면 문제없다.사냥꾼자리에 도착하는 교통이 적기 때문이다.

방문량이 많은 경우


만약 방문량이 많으면 캐시가 만료되면 여러 방문이 데이터베이스로 갈 것이다.캐시가 만료되고 새 캐시가 저장되기 전에 시체가 존재하기 때문이다.데이터베이스 처리가 너무 무거우면 캐시가 만료될 때 부하가 증가합니다.

대책


대책에는 몇 가지 방법이 있다.
  • 잠금
  • 다른 프로세스에서의 업데이트
  • 조기 만료 확률
  • 이 보도는 록 음악을 사용하는 형식의 해결 방법을 기술하였다.

    한 명만 업데이트


    캐시가 만료되면 한 사용자가 데이터베이스에 접근하여 새로운 캐시를 만들 수 있고 다른 사용자가 새로운 캐시를 기다릴 때 오리지널 사용자에 대한 부담을 줄일 수 있다.

    세태


    이런 상황에서 신호를 사용하여 접근을 제어하면 실현할 수 있다.
    무엇
    여러 개의 수행 단위가 공유 자원에 접근하는 것을 제어합니다.어떤 자원'몇 개의 기록을 사용할 수 있음을 표시'에서 사용과 해방 때의 기록을'안전하게 고쳐쓰기','기다림'조작을 자원이 사용할 수 있을 때까지 결합시킨다.
    ※ 발췌: https://ja.wikipedia.org/wiki/%E3%82%BB%E3%83%9E%E3%83%95%E3%82%A9
    그러나 웹 서비스에서 응용 프로그램은 여러 서버에서 실행됩니다.동일한 서버에서도 여러 프로세스에서 실행됩니다.따라서 각 액세스가 동일한 OS 프로세스에 있지 않으므로 OS의 (프로그래밍 언어의) 신호를 사용할 수 없습니다.
    그렇다면 어떻게 해야 할지 방문마다 공유할 수 있는 것은 캐시 시스템이기 때문에 여기에 신호를 설치했다.

    add


    memcached add 명령은 '항목이 존재하지 않는 상황에서만 저장' 입니다.즉, 단 한 명의 고객만이 이 키에 데이터를 저장할 수 있다는 것이다.
    따라서 add의 성공을 "성공"으로 간주하면 한 클라이언트가 캐시 업데이트를 할 수 있다.

    예제

    # キャッシュからデータを取得する
    data = memcache.get(key_for_data)
    
    if data:
      # キャッシュがある場合はセマフォの獲得を試みる
      ret = memcache.add(key_for_semaphore, 1, ttl=60)
    
      if ret:
        # セマフォを獲得した場合は新しいキャッシュを作る
        data = get_data_from_database(...)
        memcache.set(key_for_data, data, ttl=120)
    
    else:
      # 本当にキャッシュ切れしてしまった場合は、どうしようもないのでオリジンへアクセスします
      memcache.add(key_for_semaphore, 1, ttl=60)
      data = get_data_from_database(...)
      memcache.set(key_for_data, data, ttl=120)
    
    return data
    
    dd를 할 수 있는 사람은 한 사람뿐이기 때문에origin을 방문하는 사람은 대부분 한 사람입니다.

    유효기간


    memcache에서 프로젝트의 유효기간을 설정할 수 있습니다.따라서 유효기간이 끝나면 세태 해방이 가능하다.웹 서비스에서 HTTP 요청 처리는 즉시 회답되어 신호를 명확하게 방출할 수 없습니다.그러나 사업의 유효기간이 지났기 때문에 자동 해방도 가능하고 해방도 잊지 않을 것이다.
    또한 신호의 유효기간은 데이터 측의 유효기간보다 짧아야 한다.이렇게 하면 캐시된 데이터가 남아 있을 때 오리지널에 대한 접근과 새로운 캐시 생성이 발생하고semafor를 얻지 못한 클라이언트는 캐시된 데이터를 직접 이용할 수 있다.
    상술한 예라면key_for_semaphore은 데이터보다 먼저 기한이 지났다(ttl=60).memcache.get에서 얻은 data와 동시에 최초memcache.add에 완성된 고객은 오리온memcache.set에 방문하여 새로운 데이터를 저장했다(ttl=120).물론 캐시가 유효기간 이외의 이유로 사라지는 경우도 있기 때문에 진입else하는 경우도 있지만, 기본적으로 문제 없이 작업하고 싶다고 생각한다.

    기타


    각 소프트웨어의 Stampede 대책 기능
    - Rails ActiveSupport::Cache::Store race_condition_ttl
    - nginx proxy_cache_lock
    - Varnish Grace mode
    - Fastly
    참고 자료
    - http://techblog.yahoo.co.jp/infrastructure/cache-reducing-origin-request/
    - https://en.wikipedia.org/wiki/Cache_stampede

    좋은 웹페이지 즐겨찾기