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

읽기
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