캐싱 전략에 대해 잘 정리된 문서가 있어서 이를 번역하여 공유합니다.
오역이나 오타 및 수정사항 제보는 언제나 환영입니다
원문 출처: Caching Strategies and How to Choose the Right One | CodeAhoy
캐싱은 시스템의 성능을 향상시키는 가장 쉬운 방법입니다. DB는 느리고, 모두 알다시피 속도는 매우 중요한 문제입니다.
아래의 그래프에서 볼 수 있듯, 로드 시간이 적을수록 전환율이 높습니다.
올바르게 적용했다면 캐시는 응답 시간을 줄일 수 있고, 데이터베이스의 로드 시간을 줄일 수 있으며, 비용을 절감할 수 있습니다. 캐싱에는 몇 가지 전략이 있으며 올바른 전략을 선택하는 것이 같은 캐싱이라도 매우 큰 차이를 보일 수 있습니다.
여러분의 캐싱 전략은 데이터의 구조와 접근 패턴에 영향을 받습니다.
인기있는 모바일 게임 순위 TOP 10을 보여줘야 하는 캐싱 전략과 사용자 정보를 취합해서 제공해야 하는 서비스의 캐싱 전략은 매우 다릅니다. 옳은 캐시 전략을 선택하는 것은 성능 향상의 매우 중요한 요소입니다.
아래는 다양한 캐싱 전략에 대해 간략히 소개하는 글입니다.
일반적으로 가장 흔히 사용되는 캐싱전략으로 생각됩니다. 캐시 정보를 저장하는 저장소가 별도로 존재하며 애플리케이션(서버) 가 캐시 및 데이터베이스와 직접적으로 통신하는 구조입니다. 캐시 저장소와 주 DB와 별도로 통신을 하진 않습니다.
캐시와 데이터에 대한 모든 동작은 애플리케이션이 직접 통제합니다.
Cache Hit
로 데이터는 즉시 클라이언트에게 제공됩니다.Cache Miss
로 애플리케이션은 추가적인 작업을 해야합니다. 데이터를 가져오기 위해 DB에 쿼리를 던지고, 클라이언트에게 응답을 보낸 후 데이터를 캐시에 저장합니다. 따라서 다음에 같은 요청이 올 경우 캐시에서 즉시 데이터를 반환하여 제공할 수 있습니다.Cache-aside 전략은 가장 보편적이며 무거운 데이터를 읽는 경우에 최선에 가까운 선택지입니다. 현재는 Memcached
와 Redis
가 가장 보편적으로 사용됩니다. 해당 전략을 사용하는 경우 시스템은 캐시 실패에 유연한 대처가 가능합니다.
만약 캐시 저장소 클러스터에 문제가 생겨도 시스템은 여전히 바로 DB에서 데이터를 가져올 수 있습니다. (피크 타임에 캐시 저장소에 문제가 생기고 그에 따라 DB에서 데이터를 바로 가져오는 방식이 응답 시간에 큰 악영향을 미치는 경우라면, 응답 시간은 매우 지연되고 DB 역시 갑작스러운 부하로 문제가 생길 경우에는 큰 효과가 없을 수도 있습니다.)
다른 장점으로 DB에 저장되는 데이터의 구조와 캐시에 저장되는 데이터의 구조가 달라도 된다는 점입니다. 여러 복합적인 데이터를 필요로 하는 경우, 각 DB 엔티티의 값을 저장하는것보다는 응답에 필요한 형태의 데이터를 별도로 정의하여 캐시에 저장할 수 있습니다.(https://velog.io/@zenon8485/%EC%97%85%EB%AC%B4-%EC%BA%90%EC%8B%9C-%EC%84%B1%EB%8A%A5-%EA%B0%9C%EC%84%A0-%EB%AC%B6%EC%9D%8C-%EC%BA%90%EC%8B%B1)
Cache-aside 전략을 사용할 때 일반적인 데이터 쓰기 전략은 바로 DB에 값을 저장하는 것입니다. 그러나 이렇게 할 경우 DB와 캐시에 저장된 값이 서로 불일치할 수 있습니다. 이를 해결하기 위해서, 일반적으로 TTL(Time To Live) 정보를 활용하여 특정 시간이 지나면 다시 DB에서 값을 조회합니다.
만약 데이터의 최신성이 반드시 보장되어야 한다면, 캐시 정보 자체를 무효화하거나 올바른 write 전략을 사용해야 합니다. 아래에서 확인하도록 하겠습니다.
Read-Through 캐시는 DB와 하나의 라인(프로세스)에 묶입니다. Cach Miss
가 발생했을때, DB로 부터 데이터를 가져와 캐시에 저장한 후 애플리케이션에 반환합니다.
Cache-aside 와 Read-through 전략은 모두 데이터를 처음 읽으면 그제서야 데이터를 가져오기 때문에 lazily
하게 데이터를 가져오는 전략입니다.
Read-through와 Cache-aside 전략은 매우 비슷하지만, 두 가지 차이점이 존재합니다.
Read-through 캐시 전략은 읽기 부하가 크고 반복적으로 같은 데이터에 대한 요청이 있는 경우에 적합합니다. 예를들어, 뉴스 스토리가 있습니다. 단점으로는 데이터가 처음 요청되는 경우에는 무조건 Cache-Miss 가 발생하고 데이터를 DB에서 조회해야 하는 것입니다. 개발자는 이를 위해 사전에 미리 DB에서 데이터를 조회해 캐시에 저장하는 방식으로 문제를 극복할 수 있습니다.
cache-aside 전략과 마찬가지로 DB와 캐시에 저장된 정보에 불일치가 있을 수 있습니다만, 이에 대한 해결책인 write 전략을 아래 이어지는 글에서 확인하실 수 있습니다.
여기 애플리케이션이 데이터를 처음 쓰거나 업데이트할 때 무슨 일이 일어나는지를 설명하는 그림입니다.
1. 애플리케이션은 데이터를 즉시 캐시 저장소에 저장한다.
2. 캐시 저장소는 메인 DB에 데이터를 업데이트한다. 쓰기 작업이 완료되면, 캐시와 DB는 모두 같은 값을 가지고 데이터의 동일성을 보장한다.
별일 아닌거 같지만 먼저 캐시에 데이터를 저장한 이후 DB에 데이터를 저장하기 때문에 (두 번의 쓰기 작업) 사실은 추가적인 지연이 발생합니다. 그러나 read-through 전략과 함께 사용할 경우 언제나 데이터의 최신성을 보장할 수 있기 때문에 캐시 무효화 문제에 대해서는 해방될 수 있습니다.
DynamoDB Accelerator (DAX) 는 read-through / write-through 캐싱 전략의 좋은 예제입니다. 이 서비스는 DynamoDB 와 애플리케이션은 한 라인단위로 묶기 때문에 DynamoDB 에 대한 읽기와 쓰기 작업은 DAX 를 통해 수행됩니다.
(DAX 를 도입할 계획이 있다면 its data consistency model 에 대해 반드시 숙지하고 있어야 합니다)
데이터를 쓸 때 DB에 우선 저장을 하고 데이터를 조회하는 요청이 오면 그때 가져온 데이터를 캐시에 저장하는 방식입니다.
Write-around 전략은 Read-through 와 함께 사용될 경우 데이터를 한 번 쓰고 거의 호출하지 않는 상황에서 좋은 성능 향상을 꾀할 수 있습니다. 예를 들어, 실시간 로그 또는 채팅방의 메세지의 경우가 그렇습니다. 마찬가지로 이 전략은 cache-aside 전략과도 조합할 수 있습니다.
애플리케이션이 데이터를 우선적으로 캐시에 저장후 곧바로 클라이언트의 요청에 응답한 후, 나중에 쌓인 데이터를 한 번에 DB에 저장하는 방식입니다.
Write-Through 전략과 매우 유사하지만 한 가지 결정적인 차이가 있습니다.
애플리케이션의 관점에서, 응답하기 전에 캐시 저장소에만 데이터가 업데이트 되기만하면 되므로 속도는 향상됩니다.
이는 Write-Behind 전략이라고도 합니다.
Write-Back 전략은 쓰기 성능을 향상시키고 쓰기에 부하가 큰 경우에 적합합니다. Read-Through 전략과 함께 사용될 경우, 최근에 업데이트 된 데이터의 경우 언제나 캐싱되어 있기 때문에 복합적인 부하에 적합합니다.
이 전략은 DB에 일시적으로 부하가 걸리거나 문제가 생기는 상황에서 서비스가 어느정도 내성을 가질 수 있습니다. DynamoDB 처럼 요청에 따라 과금이 발생하는 서비스를 이용할 경우 배치 또는 병합을 지원하여 전체적인 데이터 쓰기 작업을 줄임으로써 부하를 줄이고 비용도 절감할 수 있습니다. DAX의 경우 write-through 전략을 사용하기 때문에 애플리케이션이 쓰기 집약적인 동작을 수행할 경우에는 비용 절감 효과를 기대할 수 없습니다.
몇몇 개발자는 Cache-Aside 전략과 Write-Back 전략을 함께 사용하면서 특정 시간대에 몰리는 요청을 처리합니다. 그러나 캐시 저장소에 문제가 생길 경우, 영구적으로 데이터를 잃을 수 있다는 단점이 있습니다.
대부분의 DB 저장소 엔진(InnoDB)는 write-back 캐시를 내부에 기본적으로 가지고 있습니다. 따라서 쿼리는 처음에 메모리에 저장되었다가 나중에 디스크로 전달됩니다.