⭐️. 캐싱 전략

캐싱 전략

  • 인메모리 캐시에 데이터를 저장하고 조회할 때 여러가지 전략을 사용해 효율적이고 고성능의 기능을 구현할 수 있다.

읽기

Cache Aside

  • 데이터를 조회할 때 캐시로부터 데이터를 먼저 조회해보고, 데이터가 없다면 DB에 저장된 데이터를 가져와 캐시에 저장하고 해당 데이터를 반환한다.

  • 캐시 서버가 다운되더라도 DB를 통해 데이터를 가져올 수 있기 때문에 서비스 자체에는 문제가 없다. 하지만 캐시 서버에 들어갈 부하가 DB로 몰려 장애가 발생할 가능성은 있다.

  • 첫 조회 시 반드시 DB에서 데이터를 가져와야 하므로 반복적으로 동일 쿼리를 수행하는 서비스에 적합하다.

  • 이를 위해 서비스 배포 시 미리 캐시 서버에 데이터를 입력해두는 Cache Warming 작업을 수행하기도 한다.

Read Through

  • 캐시에서만 데이터를 읽어오도록 한다.

  • 데이터 동기화를 라이브러리 또는 캐시 제공자에게 위임하므로, 캐시에 데이터가 없는 경우 캐시 서버 자체에서 DB에서 데이터를 가져와 저장한다.

  • 데이터 조회를 캐시로부터만 수행하기 때문에 캐시 서버가 다운될 경우 장애가 발생한다.

  • 캐시와 DB 간 데이터 동기화가 항상 이루어지므로 데이터 정합성 문제가 없다.

쓰기

Write Back

  • 모든 데이터를 일단 캐시에 저장해두고, 일정 주기마다 배치 작업으로 DB에 저장하는 방식이다.

  • Write가 빈번하면서 Read를 하는데 많은 양의 Resource가 소모되는 서비스에 적합하다.

  • 자주 접근되지 않는 데이터가 저장되어 리소스의 낭비가 있을 수 있다. 이를 막기 위해 TTL을 적당히 지정해주어야 한다.

  • 캐시에는 늘 최신 데이터가 저장되고, hit ratio는 100%가 될 것이다.

  • DB로 데이터들이 저장되기 전에 캐시 서버에 장애가 발생하면 데이터가 소실될 수 있다.

Write Through

  • 데이터를 저장할 때 캐시와 DB 모두에 저장하는 방식이다. DB에 저장하는 작업은 캐시에 위임한다.

  • DB와 캐시가 늘 동기화되어있는 상태가 된다.

  • write가 빈번할 경우 성능이 저하될 수 있다.

  • 자주 접근되지 않는 데이터가 저장되어 리소스의 낭비가 있을 수 있다. 이를 막기 위해 TTL을 적당히 지정해주어야 한다.

Write Around

  • 데이터를 DB에만 저장해둔다.

  • 캐시 미스가 발생하는 경우에만 DB로부터 데이터를 읽어 캐시에 저장한다.

  • DB 데이터가 변경되었을 때 캐시의 데이터가 함께 바뀌지 않으므로, 캐시와 DB 간의 데이터 불일치가 발생할 수 있다.

캐시 워밍

  • 캐시 클러스터를 스케일 아웃/업 하여 새로운 복제 노드가 생겼을 때 캐시 미스가 발생하여 백엔드에 요청이 많이 들어갈 수 있다.

  • 복수의 캐시 노드에 중복 쓰기를 하면서 새로운 노드에는 TTL을 길게 두고 이전 노드에는 TTL을 짧게 두어 점차 데이터를 이동시킬 수 있지만, 기존에 존재하는 아이템에 대한 수정이 이뤄지지 않는 경우 쓰기 연산이 수행되지 않으며 양 쪽에 데이터를 유지해야 하므로 리소스가 더 소모된다.

  • Netflix에서 개발한 캐시 워밍 방식은 다음과 같다.

캐시 워밍 방식

종류

  • Replica Warmer

    • 기존에 존재하는 클러스터의 데이터들을 클라이언트에게 영향을 주지 않은 채 가능한 빨리 새 클러스터로 복제하는 방식

  • Instance Warmer

    • 하드웨어 등의 이슈로 인해 노드(인스턴스)가 종료되거나 대체된 노드가 존재하면, 기존 노드의 데이터를 사용해 새로운 노드를 시작하는 방식

Key Dumps 기능 활용

  • 캐시 워밍이 필요한 경우, key dump 기능을 통해 노드로부터 키와 메타데이터를 로컬 파일로 저장한 후 Amazon S3에 저장한다.

  • key dump는 memcached LRU crawler에 의해 수행된다.

아키텍처

  • Controller

    • orchestrator 역할을 한다.

    • 환경을 구성한다.

    • Dumper, Populator 간의 메시지 큐를 구성한다.

    • 데이터를 복사할 기존 노드를 유저가 지정하거나 컨트롤러가 아이템이 많은 순으로 선택할 수 있다.

    • Dumper가 key dump를 시작하면 컨트롤러는 Populator 클러스터를 만들고 메시지 큐에 있는 데이터를 사용해 새로운 노드에 적용한다.

    • 메시지 큐에 더이상 데이터가 들어오지 않는다면 populator 클러스터, 메시지 큐 등 리소스를 제거한다.

  • Dumper

    • Memcached에 매핑되는 사이드카로, 톰캣 웹서버에서 memcached key dump를 생성하도록 한다.

    • Dumper는 key dump 파일을 기반으로 해당 키에 대한 value들을 조회한 후 이 값들을 모아 별도 파일로 저장한다. 이 때 value를 담은 파일은 max chunk size에 의해 크기가 제한된다.

    • 하나의 파일이 완성되면 Amazon S3에 올린 후, 메시지 큐에 해당 파일의 URL을 전달한다.

    • 이러한 방식으로 인해 모든 dump가 끝난 후 노드에 데이터가 적용되는 것이 아닌, dump 작업은 계속 수행하면서 동시에 노드에 데이터를 저장할 수 있다.

  • Populator

    • Dumper가 생성한 dump 파일을 s3로부터 다운받은 후, 데이터들을 새로운 노드에 저장하는 역할을 한다.

    • 웜업 작업 도중에 사용자가 해당 노드에 키에 대한 데이터를 생성했을 수 있으므로, 값이 없을 때에만 데이터를 추가하도록 한다.

    • 메시징 큐의 크기에 따라 Populator 클러스터를 스케일 아웃 할 수 있다.

출처

Last updated