Cache
캐쉬란 데이터 요청 주체와 메모리 저장공간 사이에 위치하면서 메모리 저장공간에 대한 조회 요청을 앞에서 먼저 대신 처리해주는 저장장치이다.
직접적으로 데이터 처리 로직을 실행 하지않고 이전에 조회된 데이터를 다시 가져오는 방식이기 효율성을 얻기 적이지만 일관성을 일부 양보하는 전략이라고 할 수 있다
Read 보다 Write가 빈번하게 일어나야 하거나 데이터 정합성이 중요한 경우 Cache를 사용하기 부적합하다
지역성의 원리
Hit ratio 를 높이는 방식으로 cache 에 데이터를 저장하는 것이 중요하며 이때 지역성의 원리가 적용된 알고리즘이 주로 사용된다.
시간 지역성(Temporal locality)
- 최근에 요청된 데이터가 다시 요청될 확률이 높다.
- For, while 같은 반복문에 사용되는 조건 변수처럼 한번 참조된 데이터는 잠시후 참조될 가능성이 높다.
공간 지역성(Spatial locality)
- 요청된 데이터 주변 메모리 데이터가 요청될 확률이 높다.
- a[0], a[1]처럼 같은 데이터 배열에 연속적으로 접근할때 참조된 데이터 근처에 있는 데이터가 잠시 후 사용될 가능성이 높다.
읽기 전략(Read Cache Strategy)
Look Aside (Cache Aside)
데이터를 찾을때 우선 캐시에 저장된 데이터가 있는지 우선적으로 확인하는 전략.
만일 캐시에 데이터가 없으면 DB에서 조회함 (Lazy Loading)
- Cache Store와 Data Store(DB)간 정합성 유지 문제가 발생할 수 있다
- 초기 조회 시 무조건 Data Store를 호출 해야 하므로 단건 호출 빈도가 높은 서비스에 적합하지 않다. 대신 반복적으로 동일 쿼리를 수행하는 서비스에 적합한 아키텍처이다
- 캐시서버 다운시 캐시에 붙어있던 connection이 많았다면, 다운된 순간 순간적으로 DB로 몰려서 부하 발생
- DB에서 캐시로 데이터를 미리 넣어주는 Cache Warming을 하기도 한다 (Thundering Herd Problem 대비)
- 캐시 서버가 다운 되더라도 DB에서 데이터를 가져올수 있어 서비스 자체는 문제가 없음
Read Through (Inline cache)
캐시에서만 데이터를 읽어오는 전략, 데이터 동기화를 라이브러리 또는 캐시 제공자에게 위임
- 캐시와 DB간의 데이터 동기화가 항상 이루어져 데이터 정합성 문제에서 벗어날수 있음
- 직접적인 데이터베이스 접근을 최소화하고 Read 에 대한 소모되는 자원을 최소화할 수 있다
- 데이터 조회를 전적으로 캐시에만 의지하므로, 캐시 서버가 다운될 경우 서비스 이용에 차질이 생길수 있음
- 캐시 서버와 같은 구성 요소를 Replication 또는 Cluster로 구성하여 가용성을 높여야 한다
cf. Thundering Herd Problem
캐시 데이터가 없는 상태에서 동시에 동일한 많은 요청이 발생시 Cache Miss가 발생하고 캐시는 요청을 처리하기 위해 결국 원본 서버에게 요청, 원본 서버의 부하를 줄이기 위해 구축된 캐시가 무용지물, 이 문제를 Thundering Herd Problem 이라 한다
solve
1. Cache Warming
2. 동시에 동일한 많은 요청이 들어오면 하나의 Cache Miss만 원본 서버에 요청하고 나머지 요청을 잠시 대기시킨 후, 응답이 돌아오면 그 응답을 반환
- Nginx, Apache Traffic Server 등 여러 웹 서버, 프록시 서버 솔루션에서 Thundering Herd Problem을 해결하기 위한 옵션들을 제공
쓰기 전략(Write Cache Strategy)
Write Back (Write Behind)
데이터를 저장할때 DB에 바로 쿼리하지않고, 캐시에 모아서 일정 주기 배치 작업을 통해 DB에 반영, 캐시가 일종의 Queue 역할을 겸하게 된다
- DB 쓰기 횟수 비용과 부하를 줄일 수 있지만, 데이터를 옮기기 전에 캐시 장애가 발생하면 데이터 유실이 발생할 수 있다는 단점이 존재
- Replication이나 Cluster 구조를 적용함으로써 Cache 서비스의 가용성을 높이는 것이 좋음
- 읽기 전략인 Read-Through와 결합하면 가장 최근에 업데이트된 데이터를 항상 캐시에서 사용할 수 있는 혼합 워크로드에 적합
Write Through
데이터를 저장할 때 먼저 캐시에 저장한 다음 바로 DB에 저장 (모아놓았다가 나중에 저장이 아닌 바로 저장)
Read Through 와 마찬가지로 DB 동기화 작업을 캐시에게 위임
- DB와 캐시가 항상 동기화 되어 있어, 캐시의 데이터는 항상 최신 상태로 유지
- 캐시와 백업 저장소에 업데이트를 같이 하여 데이터 일관성을 유지할 수 있어서 안정적
- 자주 사용되지 않는 불필요한 리소스 저장, 리소스 낭비 가능성이 있다.
- 매 요청마다 두번의 Write가 발생하게 됨으로써 빈번한 생성, 수정이 발생하는 서비스에서는 성능 이슈 발생
- Write-Through 패턴과 Read-Through 패턴을 함께 사용하면, 캐시의 최신 데이터 유지와 더불어 정합성 이점을 얻을 수 있다.
cf. Key Expire
write throuth 패턴과 write back 패턴 둘 다 모두 자주 사용되지 않는 데이터가 저장되어 리소스 낭비가 발생되는 문제점을 안고 있기 때문에, 이를 해결하기 위해 TTL을 꼭 사용하여 사용되지 않는 데이터를 반드시 삭제해야 한다
Write Around
쓰기 오퍼레이션에 의해 캐시 업데이트 하지 않는다. 캐시가 로드 되는 시점은 해당 데이터가 캐시에 요청되고 miss 가 발생했을때 로드 한다
- 기록하는 데이터가 자주 사용되지 않는 경우에 적합하다
- 데이터베이스에 저장된 데이터가 수정되었을 때, 사용자가 조회하는 cache와 데이터베이스 간의 데이터 불일치가 발생
- 데이터베이스에 저장된 데이터가 수정, 삭제될 때마다, Cache 또한 삭제하거나 변경해야 하며, Cache의 expire를 짧게 조정하는 식으로 대처해야 한다.
- Write Around 패턴은 주로 Look aside, Read through와 결합해서 사용된다
Reference
'개발' 카테고리의 다른 글
메시지 전달 보증 (Message Delivery Guarantee) (0) | 2023.06.18 |
---|---|
Redis Fragmentation (0) | 2023.06.18 |
Redis cache eviction (0) | 2023.06.15 |
OS 메모리 관리 (0) | 2023.06.15 |
Generics / Variance (0) | 2023.06.04 |