캐시는 최근 웹 서비스 환경에서 시스템 성능 향상을 위해 가장 중요한 기술입니다.
- 캐시는 메모리를 사용함으로 디스크 기반 데이터베이스 보다 훨씬 빠르게 데이터를 반환할 수 있고 사용자에게 더 빠르게 서비스를 제공할 수 있음
메모리(RAM)을 사용한 기술로 데이터베이스보다 훨씬 빠르게 데이터를 제공할 수 있지만, 제공되는 물리 RAM의 용량에는 한계가 있기 때문에 모든 데이터를 RAM에 저장할 수는 없습니다.
때문에 다양한 전략들에 대해 알아보고 상황에 알맞게 사용해야 합니다.
또한 캐시를 사용할 때 데이터 정합성을 고려해야 합니다.
데이터 정합성 문제란 일반적으로, 캐시와 데이터베이스 두 곳에서 같은 데이터임에도 불구하고 데이터값이 서로 다른 다른 문제를 말합니다. DB에서 데이터 조회와 작성을 처리하면 일반적으로 데이터 정합성 문제가 나타나지 않았지만, 캐시라는 또다른 데이터 저장소를 이용한다면 두 저장소에서 저장된 값이 서로 다를수 있는 현상이 일어날 수 있습니다.
따라서 적절한 캐시 읽기 전략(Read Cache Strategy)과 캐시 쓰기 전략(Write Cache Strategy)을 통해, 캐시와 DB간의 데이터 불일치 문제를 극복하면서도 빠른 성능을 유지해야 합니다.
캐시에는, 자주 조회되는 데이터, 결과값이 자주 변동되지 않고 일정한 데이터, 조회하는데 연산이 필요한 데이터들을 두고 사용하는 것이 좋습니다. 또한 데이터의 유실 또는 정합성이 일정 부분 깨질 수 있으므로, 중요한 정보 및 민감정보는 저장하지 않는것이 좋습니다.
Cache hit Cache miss
캐시에서 데이터를 찾는 과정에서 캐시에 데이터가 있으면 cache hit, 캐시에 데이터가 없으면 cache miss라고 부릅니다. cache hit가 발생하면 데이터를 빠르게 찾을 수 있어 처리 속도가 빨라지지만, cache miss가 발생하면 데이터를 찾기 위해 원본 데이터에 접근해야 하므로 처리 속도가 느려집니다. 따라서 적절한 캐시 전략을 선택하여 cache hit 비율을 높이는 것이 중요합니다.
캐시 전략 패턴
캐시에는 데이터를 읽을수도 있고, 쓸 수도 있기 때문에 다양한 전략이 존재합니다.
- 읽기 전략 - Look-Aside, Read Through
- 쓰기 전략 - Write Back, Write Through, Write-around
- 읽기 + 쓰기 조합 전략 - Look Aside + Wirte Around, Read Through + Write Around , Read Through + Write Through
Look Aside 패턴 (LazyLoading) - 읽기 전략
Cache Aside 패턴이라고도 불리는 이 전략은
캐시에 저장된 데이터가 있는지 우선적으로 조회하고 없다면 DB에서 조회하는 전략입니다.
- 애플리케이션이 캐시를 읽고, 애플리케이션이 캐시에 데이터가 없다면 DB를 직접 조회
- 캐시는 직접 DB와 연결되어있지 않음
Cache에 데이터가 저장되어 있다면, DB에 접근하는 대신 Cache에서 호출함으로써 DB 부하를 줄일 수 있습니다.
Redis가 다운되더라도 바로 장애로 이어지지 않고 DB에서 데이터를 가지고 올 수 있습니다.
> 반복적인 읽기가 많은 작업에 적합합니다.
장점
- 반복되는 작업을 캐시에 적재하므로 DB 부하를 줄일 수 있다. 성능도 당연히 증대.
- 만일 redis가 다운 되더라도 DB에서 데이터를 가져올수 있어 서비스 자체는 문제가 없으므로 가용성 증대
단점
- 캐시에 커넥션이 많이 붙어있었다면, DB 조회시 커넥션이 모두 몰려가 부하가 생길 수 있다.
- 해결방법 - Cache Warming : 캐시에 데이터를 미리 적재하는 작업.
- 초기 캐시에 데이터가 없으면 DB에서 데이터를 조회해 캐시에 적재하는데, 이 때 많은 부하가 생길 수 있어 미리 적재
- 일정 시간이 지나 expire 되서 데이터가 사라지고 다시 커넥션이 몰릴 수 있으므로 캐시의 TTL을 잘 설정해야함.
- 해결방법 - Cache Warming : 캐시에 데이터를 미리 적재하는 작업.
Read Through 패턴 - 읽기 전략
애플리케이션이 데이터베이스를 바라보지 않고 캐시만 바라보고 캐시에서만 데이터를 읽어오는 전략입니다.(inline cache)
Look Aside 패턴과 비슷하지만, 데이터베이스와 동기화 하는 작업은 캐시가 직접 수행합니다.
즉 애플리케이션은 DB대신 캐시랑만 통신하는것입니다.
첫 데이터 요청은 미스가 나며 그 때 데이터가 로딩되고 이후에 캐시에서 처리합니다.
- 이 캐시 미스를 방어하려면 스케쥴러 등을 이용하여 미리 캐시를 warmup 합니다
> 읽기 요청이 많은 작업에 적합합니다.
장점
- 직접적인 데이터베이스 접근을 최소화하고 Read 에 대한 소모되는 자원을 최소화
- 캐시와 DB간 데이터 동기화가 항상 이루어지기 때문에 데이터 정합성 문제에서 벗어날 수 있다.
- 처음 데이터가 요청될 때만 느리고 비용이 많이 드는 데이터 로드 작업을 수행하고, 이후 요청에 대해서는 캐시에서 빠르게 응답할 수 있다.
단점
- 캐시가 다운될 경우 서비스 이용에 문제가 생긴다.
- Replication 또는 Cluster로 구성하여 가용성을 높여야한다. -> 비용 증대
- 캐시와 데이터베이스의 강결합
Write back 패턴(Write-Behind) - 쓰기 전략
쓰기가 굉장히 빈번할 때 사용하며 DB에 바로 저장하지 않고 캐시에 먼저 저장하고 모아서 DB에 저장하는 전략입니다.
특정 시점에 별도의 서비스 (배치작업)등을 통해 캐시의 내용이 나중에 DB로 동기화 됩니다.
- 캐시의 flush 정책(LRU, FIFO, LIFO 등)에 따라 데이터가 나중에 데이터베이스에 저장됩니다.
- 캐시가 일종의 Queue 역할
캐시에 모아놨다가 DB에 쓰기 때문에 쓰기 쿼리 회수 비용과 부하를 줄일 수 있어
쓰기 요청이 많은 경우에 적합합니다.
장점
- 쓰기 비용과 데이터베이스 부하를 줄일 수 있다.
- 데이터 정합성이 확보됨.
- 데이터베이스가 장애가 발생해도 캐시로 서비스가 가능하다.
단점
- 데이터를 모아뒀다가 한번에 기록하므로 캐시에서 오류가 발생하면 데이터가 영구 소실된다.
- 자주 사용되지 않는 불필요한 리소스까지 저장해야 한다.
이 전략 또한 캐시에 Replication이나 Cluster 구조를 적용함으로써 Cache 서비스의 가용성을 높이는 것이 좋으며, 캐시 읽기 전략인 Read-Through와 결합하면 가장 최근에 업데이트된 데이터를 항상 캐시에서 사용할 수 있는 혼합 워크로드에 적합합니다.
Write Through 패턴 - 쓰기 전략
Read-Through와 마찬가지로 애플리케이션이 DB를 직접 조회하지 않고 캐시를 바라보면서 데이터를 읽고 쓰게 되는 전략입니다.
캐시가 주 데이터 저장소가 되면 데이터베이스와 동기화하는 역할은 캐시가 맡게 됩니다.
데이터를 저장할 때 먼저 캐시에 저장한 다음 바로 DB에 저장합니다.
- 모아놓았다가 저장하는 것이 아닌, 캐시와 데이터베이스에 데이터를 모두 바로 기록
- DB에 저장하는 역할은 캐시가 수행
데이터 유실이 발생하면 안되는 상황이나, 기록한 데이터를
다시 자주 읽는 경우에 적합합니다.
장점
- DB와 캐시가 항상 동기화 되어 있어, 데이터 정합성 문제를 방지하고 캐시의 데이터는 항상 최신 상태로 유지
단점
- 자주 사용되지 않는 불필요한 리소스 저장
- 이럴 때는, 일정 시간만 보관하겠다는 expire time을 설정해 주어야 한다.
- 캐시1번, DB1번 총 두 번의 쓰기 작업을 한다는 점에서 상대적으로 느리다
- 기억장치 속도가 느릴 경우, 데이터를 기록할 때 CPU가 대기하는 시간이 필요하기 때문에 성능 감소
- 두 번의 쓰기 작업이므로 수정이 발생하는 서비스에서는 성능 이슈 발생
write throuth 패턴과 write back 패턴 둘 다 모두 자주 사용되지 않는 데이터가 저장되어 리소스 낭비가 발생되는 문제점을 안고 있기 때문에, 이를 해결하기 위해 TTL을 꼭 사용하여 사용되지 않는 데이터를 반드시 삭제해야 한다. (expire 명령어)
Write-Through 패턴과 Read-Through 패턴을 함께 사용하면, 캐시의 최신 데이터 유지와 더불어 정합성 이점을 얻을 수 있습니다.
대표적인 예로 AWS의 DynamoDB Accelerator(DAX)가 있습니다.
DAX 패턴을 통해 DynamoDB에 대한 읽기 및 쓰기를 효율적으로 수행할 수 있습니다.
Write Around 패턴 - 쓰기 전략
쓰기 요청이 캐시를 거치지 않고 데이터베이스에만 저장하는 전략입니다.
캐시에 데이터가 로딩되는 시점은 언젠가 해당 데이터가 캐시에 요청이 되고 miss가 발생하였을 때 조회합니다.
즉 읽은 데이터만 캐시에 로딩됩니다.
이 전략은 기록하는 데이터가 자주 사용되지 않을 때 적합합니다.
장점
- Write Through 보다 훨씬 빠름
- 두 번의 쓰기 작업이 일어나지 않는다.
단점
- 캐시와 DB 내의 데이터가 다를 수 있음 (데이터 불일치)
- cache miss가 발생하기 전에 데이터베이스에 저장된 데이터가 수정되었을 때, 사용자가 조회하는 cache와 데이터베이스 간의 데이터 불일치가 발생하게 된다.
- 데이터베이스에 저장된 데이터가 수정, 삭제 될 때마다 캐시도 마찬가지로 수정,삭제 해주어야 하고, expire를 짧게 지정해주어야 한다.
Write Around 패턴은 주로 Look aside, Read through와 결합해서 사용된다.
데이터가 한 번 쓰여지고, 덜 자주 읽히거나 읽지 않는 상황에서 좋은 성능을 제공한다.
Look Aside + Write Around 조합 - 읽기 + 쓰기 전략 조합
이 전략은 Look-Aside와 Write-Around의 장점을 살리는 방법으로,
데이터를 읽을 때는 Look-Aside 전략을 사용하고, 데이터를 쓸 때는 Write-Around 전략을 사용합니다.
- Look Aside : 캐시에 저장된 데이터가 있는지 우선적으로 조회하고 없다면 DB에서 조회하는 전략
- Write-Around : 쓰기 요청이 캐시를 거치지 않고 데이터베이스에만 저장하는 전략
데이터를 읽을 때는 캐시에서 데이터를 먼저 찾고, 캐시에 없으면 데이터베이스에서 데이터를 가져와서 캐시에 저장한 후 반환합니다.
이때, 데이터를 가져오는 작업은 백그라운드에서 처리되어 응답 시간을 최소화합니다.
반면에 데이터를 쓸 때는 Write-Around 전략을 사용하여 캐시를 건너뛰고, 바로 데이터베이스에 쓰는 방법입니다.
이전에 쓴 데이터는 캐시에 저장되어 있지 않기 때문에, 다시 읽을 때는 데이터베이스에서 가져와야 합니다.
장점
- Look Aside 전략의 빠른 응답시간과 Write-Around 전략의 데이터 일관성 유지를 모두 가진다.
단점
- 데이터를 쓸때마다 캐시를 건너 뛰므로 응답 시간이 길어질 수 있다.
- 데이터베이스와 캐시 사이의 일관성을 유지해야 하므로 DB에서 가져온 데이터를 캐시에서도 적절히 관리해야 한다.
Read Through + Write Around 조합 - 읽기 + 쓰기 전략 조합
읽을때는 Read Through와 쓸때는 Write Around 전략을 조합하여 사용하는 방법입니다.
- Read Through : 애플리케이션이 데이터베이스를 바라보지 않고 캐시만 바라보고 **캐시에서만 데이터를 읽어오는 전략
- Write-Around : 쓰기 요청이 캐시를 거치지 않고 데이터베이스에만 저장하는 전략
이 전략에서는 먼저 Read Through 방식을 사용하여 데이터를 가져와 캐시에 저장합니다.
그리고 이후 데이터가 변경되면 Write Around 방식으로 캐시를 업데이트합니다.
이를 통해 데이터의 빈도가 낮은 경우에도 캐시 효과를 얻을 수 있습니다.
장점
- 항상 DB에 쓰고, 캐시에서 읽을때 항상 DB에서 먼저 읽어오므로 데이터 정합성 이슈에 대한 완벽한 안전 장치를 구성할 수 있음
- 데이터의 빈도가 낮은 경우에도 최초의 데이터 로딩 시간을 줄일 수 있다.
- 데이터가 업데이트되는 경우에만 캐시를 업데이트하므로 불필요한 캐시 업데이트를 줄일 수 있다.
단점
- 데이터를 쓸때마다 캐시를 건너 뛰므로 응답 시간이 길어질 수 있다.
- 데이터베이스와 캐시 사이의 일관성을 유지해야 하므로 DB에서 가져온 데이터를 캐시에서도 적절히 관리해야 한다.
- 쓰기 연산이 많은 경우에는 Write Around 방식으로 인해 캐시 효과가 감소할 수 있다.
Read Through + Write Though 조합 - 읽기 + 쓰기 전략 조합
읽기 시에는 먼저 캐시를 조회하고, 해당 데이터가 캐시에 존재하지 않는 경우에는 데이터 소스에서 조회하여 가져와 캐시에 저장합니다.
이후 다음에 같은 데이터를 읽을 때는 캐시에서 가져오므로 데이터 소스에 접근할 필요가 없습니다.
쓰기 시에는 데이터를 먼저 캐시에 저장하고, 동시에 데이터 소스에도 쓰기를 수행합니다.
이렇게 함으로써 데이터 일관성이 유지되며, 쓰기 지연 문제를 해결할 수 있습니다.
장점
- 데이터를 쓸 때 항상 캐시에 먼저 쓰므로 읽을때도 최신 캐시 데이터 및 데이터 정합성 보장
단점
- 캐시에 데이터를 쓰고 DB에도 데이터를 쓰므로 쓰기 연산의 성능이 떨어진다.
- 동일한 데이터를 다수의 클라이언트가 동시에 쓰려고 할 때 충돌이 발생하여 데이터 일관성이 깨질 가능성이 있다.
캐시 사용시 주의점
- 캐시를 구성하는 목적은 빠른 성능 확보와 데이터 전달에 있으며, 데이터의 영속성을 보장하기 위함이 아니라는 점을 기억하고 설계해야 한다.
- 캐시 서버가 장애로 부터 복구되는 동안 성능상의 지연은 발생할 수 있지만, 서비스가 불가능한 상태가 되지 않도록 고려해야 한다
- 데이터 정합성을 어떻게 유지할것인가에 대해 고민해야 한다. 데이터의 충돌이 일어나서는 안된다.
- 여러 애플리케이션이 캐시를 공유한다면 한 애플리케이션이 데이터를 수정하는 경우 다른 애플리케이션은 업데이트나 덮어쓰기가 일어나지 않도록 해야한다.
- 데이터 검색 후 변경되지 않았는지에 일일히 확인하거나, 캐시 데이터를 업데이트 하기 전에 Lock을 거는 방식등이 있다.
- 캐시의 만료 정책을 잘 고려해야 한다. 오래된 정보가 캐싱되어 있어 정합성에 문제가 생길 수 있다.
- 캐시된 데이터가 기간 만료 되면 캐시에서 데이터가 제거 되고, 응용 프로그램은 원래 데이터 저장소에서 데이터를 검색 해야 한다.
- 캐시 만료 주기가 너무 짧으면 데이터는 너무 빨리 제거되고 캐시를 사용하는 이점은 줄어들고, 너무 길면 데이터 정합성이 맞지 않거나, 변경될 가능성이 높고 메모리 부족 현상이 발생할 수도 있다.
- 대규모 트래픽 환경에서 TTL 값이 너무 작게 설정되면 cache stampede 현상이 발생할 가능성이 있다.
참조
- https://www.youtube.com/watch?v=92NizoBL4uA
- https://escapefromcoding.tistory.com/703
- https://inpa.tistory.com/entry/REDIS-%F0%9F%93%9A-%EC%BA%90%EC%8B%9CCache-%EC%84%A4%EA%B3%84-%EC%A0%84%EB%9E%B5-%EC%A7%80%EC%B9%A8-%EC%B4%9D%EC%A0%95%EB%A6%AC
- https://velog.io/@hwaya2828/Redis-%EC%BA%90%EC%8B%9C-%EC%A0%84%EB%9E%B5
- https://happyer16.tistory.com/entry/%EB%A0%88%EB%94%94%EC%8A%A4Redis%EC%9D%98-%EB%8B%A4%EC%96%91%ED%95%9C-%ED%99%9C%EC%9A%A9-%EC%82%AC%EB%A1%80
'Database > Redis' 카테고리의 다른 글
레디스를 활용한 분산 락(Distrubuted Lock) feat lettuce, redisson (0) | 2023.08.27 |
---|---|
Redis 자료구조와 트랜잭션 (0) | 2023.04.29 |
Redis 야무지게 사용하기 (0) | 2023.04.29 |