redis

[redis] 캐시 전략

엄지성 2024. 9. 9. 00:49

캐시 전략

캐시 전략은 웹 서비스를 운영하는데 성능 향상을 기대할 수 있는 중요한 기술이다.

보통 캐시를 사용하면 메모리 공간을 사용하기 때문에 쿼리를 보내는 데이터베이스에 비해 빠르게 데이터를 응답하는 성능을 보여준다.

 

하지만 보통 메모리 공간이 16 ~ 32G 정도라서 모든 데이터들을 캐싱한다면 메모리가 터져 애플리케이션이 멈춰버릴지 모른다.

그런 사고를 대비하기 위해 캐시 전략을 공부하여 예방과 성능을 높여야 된다.

 

본론에 들어가기 전에 알아야 되는 단어가 존재한다. 그것은 Cache Hit과 Cache Miss이다.

  • Cache Hit: 캐시 저장소에 이미 데이터가 존재하여 바로 응답할 수 있는 경우
  • Cache Miss: 캐시 저장소에 데이터가 존재하지 않아서 DB에서 데이터를 가져와야 되는 경우

캐시 중 문제점

하지만 무작정 캐싱을 하여 성능을 챙기면 좋겠지만 문제점이 존재한다. 그것은 데이터 정합성이다.

여기서 말하는 데이터 정합성은 캐시에 존재하는 데이터가 DB에 존재하는 데이터임에도 저장소의 데이터의 내용이 일치하지 않는다는 문제점이다. 캐시를 사용하기 전에는 DB에서 데이터를 가져와 문제가 되지 않았지만 이젠 다르다. DB와 Redis 두 개의 데이터 저장소를 사용하기 때문에 데이터가 일치하지 않는 문제점이 생길 수밖에 없다. 

 

이런 경우는 운영 중인 애플리케이션에서 일어난다면 좋지 않다. 그래서 우리는 캐시 읽기 전략과 캐시 쓰기 전략을 공부하여 데이터 불일치가 일어나지 않게 조심하고 또한 성능도 챙기는 그런 캐시를 지향해야 된다. 그래서 한번 알아보자.


캐시 읽기 전략(Read Cache Strategy)

Look Aside 전략

이 전략은 우선 캐시 저장소(Redis)에 먼저 조회를 한다. 만약에 캐시 저장소에 데이터가 존재하지 않으면 DB로 조회를 한다.

이 전력은 반복적인 읽기가 많은 애플리케이션에 적용하면 좋은 성능이 될 것이다. 또한, 캐시와 DB가 분리되어 있어 원하는 데이터만 캐시에 저장하여 레디스에 저장할 수 있다는 점과 캐시가 만약에 다운되더라도 DB에 조회하기 때문에 애플리케이션에 문제가 생기지 않는다.

 

다만, 레디스에 연결된 커넥션이 많다면 순간적으로 DB에 쿼리가 많이 보내져 성능이 저하된다는 단점이 존재한다.

 

이 패턴은 캐싱할 때 많이 사용하는 캐싱 전략 중 하나이다.

 

 

  1. Cache Store에 저장되어 있는지 확인
  2. Cache Store에 저장된 데이터가 없으면 DB에 조회
  3. DB에 조회한 데이터를 Cache Store에 저장

이 전략은 캐시 저장소의 장애가 발생하더라도 DB에 요청하면 되기 때문에 상관없지만 나중에 데이터 정합성 문제가 발생할 수 있다. 또한, 처음 요청할 때 캐시 저장소를 호출하기 때문에 단건 호출보단 반복적인 호출에 사용하는 애플리케이션에 사용하는 것이 좋은 전략입니다.

 

처음 요청에 캐시 저장소에 데이터를 요청한다고 하였다. 그러면 응답은 늦어질 수밖에 없을 것이다. 그래서 이것을 예방하기 위해 캐시 스토어에 데이터를 미리 넣어놓는 작업을 하기도 하는데 이것을 Cache Warming이라고 한다.

더보기

Cache Warming?

 

Cache Warming은 캐시 스토어에 데이터를 미리 넣어놓는 작업이라고 했다. 간단하게 말하면 워밍업 같은 느낌이다.

트래픽이 많은 애플리케이션에 이 작업을 하지 않는다는 가정을 해보면 트래픽이 급증한다고 하면 Cache Miss가 일어난다. 그러면 당연히 DB에 많은 쿼리가 보내지고 그럼 DB에 부하가 갈 수밖에 없다.(Thundering Herd)

하지만 캐시 저장소도 계속 데이터를 저장할 수 없어 언젠간 만료가 된다. 그러면 또 Cache Miss가 일어날 것이고 똑같은 상황이 발생할 것이다. 그런 점을 생각해서 TTL을 잘 설정하면 좋을 것 같다.

 

Read Through 패턴

이 전략은 캐시에서만 데이터를 읽는 패턴이다. 보기에는 위에 Look Aside와 비슷하지만 데이터 동기화를 라이브러리 혹은 캐시 제공자에게 위임하는 방식이다. 그래서 데이터를 조회하는 것이 느리다.

 

그리고 데이터 조회를 캐시에 의존하기 때문에 redis가 다운된다면 서비스 이용에 차질이 생길 수가 없다. 하지만 DB와 계속해서 동기화를 진행하기 때문에 데이터 정합성은 걱정할 필요가 없다. 이것 또한 읽기가 많은 애플리케이션에 적합하다.

 

 

  1. Cache Store에 요청하는 데이터가 있는지 확인
  2. 없으면 DB에 조회해 Cache Store에 업데이트
  3. Cache Store에 데이터를 가져옴

Read Through 패턴은 Look Aside과 비슷하지만 차이점이라고 하면 Cache Store에 저장하는 주체가 서버인지 아니면 DB인지의 차이점이다. 이 방식은 직접적인 DB의 접근을 최소화하고 읽기에 대한 자원 소비를 최소화할 수 있다.

 

하지만 이런 방식은 Redis가 문제가 생긴다면 전체 서비스의 중단 사태로 이어질 수 있다. 그래서 redis와 같은 구성 요소를 Replication 또는 Cluster로 구성하여 가용성을 높여야 한다. 이 패턴 또한 Look Aside와 같이 Cache Warming을 하면 더 좋은 성능을 보여줄 수 있다.

더보기

Replication

: 실시간 복제본 데이터베이스 서버를 운용하는 것

 

Cluster

: 고성능 컴퓨팅을 위해 여러 단말의 컴퓨터로 구성된 컴퓨터 집합


캐시 쓰기 전략(Write Cache Strategy)

Write Back 패턴

이 전략은 캐시와 DB 간의 동기화를 하지 않아 동기화를 생략한다. 그래서 데이터를 DB에 바로 쿼리를 보내지 않고 캐시를 모아 일정 주기의 배치 작업으로 DB에 업데이트한다. 이런 점이 쓰기 비용과 DB의 부하를 줄일 수 있다. 하지만 Redis의 부하가 갈 수도 있다.

 

이 패턴이 사용되면 좋은 서비스는 Write가 자주 일어나고 Read를 하는데 많은 양의 자원이 사용되는 서비스에 적합할 수 있다. 이유는 쓰기가 자주 되는 것은 DB에 쿼리가 자주 보내진다는 것이고 Read도 물론 쿼리를 보내야 되기 때문에 Redis를 사용해서 읽기와 쓰기가 빠르게 되는 장점을 이용하면 좋은 성능을 보여줄 수 있기 때문이다.

 

 

  1. 모든 데이터를 캐시 저장소에 저장
  2. 일정 주기마다 DB에 저장

이 방식을 다시 말하면 데이터를 DB에 바로 저장하지 않고 캐시 저장소에 저장하여 일정 기간 동안 데이터를 모아놓았다가 해당 시간이 되면 DB에 저장하는 방식이다. 이런 방식이 DB의 쓰기 읽기 비용을 줄일 수 있지만 그전에 Redis에 문제가 발생한다면 DB에 저장도 되지 않아 심각한 문제가 발생할 수 있다. 하지만 긍정적으로 반대로 생각해 보면 DB에 문제가 생겨도 Redis에 모든 데이터를 저장하기 때문에 Write, Read에 문제가 생기지 않는다.

 

더보기

이 방식도 위에 설명한 Read Through 방식처럼 Replication과 Cluster를 적용하면 가용성을 높일 수 있고 Read Through와 결합하여 사용한다면 가장 최신 데이터를 캐시에서 사용할 수 있는 혼합 워크로드에 적합하다.

 

// 워크로드는 컴퓨팅 리소스가 작업 완료 또는 결과 도출을 위해 수행하는 처리 작업의 유형과 양

 

Write Through 패턴

이 패턴은 DB와 redis에 동시에 데이터를 저장하는 패턴이다. 위에 Write Back처럼 한 번에 저장하는 것이 아닌 Redis에 먼저 저장을 하였다가 바로 DB에 저장하는 방식이다. 이런 방식 덕분에 동기화를 Redis에 위임한다. 또한 Redis와 DB가 항상 최신의 데이터를 유지하여 데이터 일관성을 지킬 수 있다. 이런 방식은 데이터가 유실되지 않게 방지하는 것에도 적합하다.

 

 

  1. DB에 저장할 데이터를 우선 캐시에 저장
  2. 캐시에 저장한 데이터를 DB에 저장

이런 방식 때문에 항상 캐시와 DB가 동기화가 되어있다는 장점이 있다.

동기화도 중요하지만 상대적으로 두 번 저장을 해야 되는 작업이기 때문에 느리다는 단점이 있고 무조건 DB에 저장하기 전에 캐시에 저장하기 때문에 나중에 사용하지 않을 데이터도 캐시에 저장되어 있어 리소스가 낭비된다는 단점도 있다.

 

이런 단점을 보안하기 위해서는 Redis의 데이터 TTL을 잘 설정하는 것이 예방 방법이다.

 

Write Around 패턴

Write Through보다 빠르다는 장점이 있는 패턴이다. 이 패턴은 모든 데이터를 캐시를 거치지 않고 바로 DB에 저장하는 것이 특징이다.

또한 Cache Miss가 일어나는 경우에 캐시에도 데이터를 저장한다. 따라서 DB와 캐시 저장소의 데이터 불일치 문제점이 생길 수 있다.

 

이 패턴은 속도는 빠르지만 문제점은 데이터가 수정되거나 삭제되었을 때 캐시에 있는 데이터와 달라 불일치 문제가 생기는 점인데 이런 점을 예방하기 위해서는 TTL을 이용하거나 다른 패턴과 결합하는 방식이다. 이 패턴과 잘 어울리는 패턴은 Look Aside와 Read Through 패턴이라고 할 수 있다.


자주 쓰이는 조합(패턴)

Look Aside && Write Around

  • 데이터를 바로 DB에 저장
  • 데이터를 요청하면 캐시에 있는지 확인 -> 있으면 반환
  • 없으면 DB에서 데이터를 캐시에 저장 후 반환

 

Read Through && Write Around

  • 모든 데이터를 바로 DB에 저장
  • 데이터 요청 시 캐시를 확인
  • 캐시는 DB와 계속 동기화하기 때문에 바로 반환
  • 이 방식은 데이터 정합성의 이슈를 아예 걱정하지 않을 수 있는 패턴 방식

 

Read Through && Write Through

  • 데이터를 저장할 때 무조건 캐시에 먼저 저장하기 때문에 최신 캐시와 빠른 응답 속도
  • 또한, 데이터를 캐시에 먼저 저장 후 DB에 보내기 때문에 데이터 정합성 보장