Redis가 왜 빠른지 두 번 눌러보기

같은 데이터를 두 번 불러보고 가격 변경과 동시 요청까지 비교하며 Redis 캐시, TTL, 무효화와 요청 몰림을 익힙니다.

Redis를 처음 배울 때 SET, HSET, LPUSH 같은 명령부터 보면 어렵게 느껴집니다. 하지만 가장 익숙한 쓰임은 간단합니다.

자주 찾는 데이터를 잠시 기억해 두고, 다음 요청에 빠르게 돌려주는 것.

이 데모는 그 한 가지 장점만 보여줍니다.

같은 데이터를 두 번 불러보세요

상품 정보를 처음 요청하면 Redis에는 아직 값이 없습니다.

  1. Redis에서 값을 찾습니다.
  2. 값이 없으므로 원본 DB까지 갑니다.
  3. DB에서 받은 상품 정보를 Redis에 잠시 저장합니다.

같은 상품을 다시 요청하면 흐름이 짧아집니다.

  1. Redis에서 저장된 값을 찾습니다.
  2. 원본 DB를 다시 읽지 않고 바로 응답합니다.

이를 캐시 적중이라고 합니다. 반복 요청이 많을수록 빠른 응답이 늘고, 원본 DB가 처리해야 하는 읽기도 줄어듭니다.

Redis 자체가 빠른 것과 캐시가 빠른 것은 다릅니다

Redis는 데이터를 주로 메모리에서 다루고, 문자열·해시·리스트 같은 자료 구조를 바로 조작할 수 있어서 빠른 읽기와 쓰기에 유리합니다.

이 데모가 보여주는 것은 그보다 한 단계 더 바깥의 효과입니다. 캐시가 적중하면 원본 DB 조회와 데이터 가공 과정을 건너뛰므로, 사용자에게 응답하기까지의 길도 짧아집니다. 즉 Redis 자체의 빠른 처리원본 작업을 생략해서 얻는 시간이 함께 작용합니다.

다만 메모리를 쓴다는 이유만으로 모든 요청이 언제나 빨라지는 것은 아닙니다. 네트워크 거리, 데이터 크기, 사용하는 명령, 저장 설정과 서버 부하에 따라 실제 성능은 달라집니다.

오래된 값은 계속 남겨두지 않습니다

캐시에는 보통 TTL이라는 유효 시간을 둡니다. 시간이 끝나면 값이 자동으로 만료되고, 다음 요청은 다시 DB에서 최신 값을 가져옵니다.

TTL이 짧으면 최신 값에 가깝지만 DB를 더 자주 읽습니다. TTL이 길면 캐시 적중은 늘지만 오래된 값을 잠시 보여줄 수 있습니다. 서비스 성격에 맞게 균형을 정해야 합니다.

값이 바뀌는 순간에도 규칙이 필요합니다. 상품 가격을 DB에서 수정했는데 이전 캐시가 남아 있으면 TTL이 끝날 때까지 오래된 가격을 보여줄 수 있습니다. 흔히 쓰는 선택은 다음 두 가지입니다.

  • DB 갱신에 성공한 뒤 해당 캐시 키를 지워 다음 읽기가 다시 채우게 합니다.
  • 아주 짧은 지연도 허용할 수 없다면 갱신과 캐시 무효화가 어긋났을 때 복구할 재시도·이벤트 처리를 둡니다.

데모의 DB 가격만 79,000원으로 변경 실험에서는 이 차이를 직접 확인할 수 있습니다. 원본 DB의 가격을 바꿔도 Redis에는 이전 89,000원이 남습니다. 캐시에서 다시 읽으면 응답은 빠르지만 가격은 오래된 상태입니다. 캐시를 지운 다음 요청해야 DB의 새 가격을 읽고 Redis도 다시 채워집니다.

여기서 중요한 점은 빠른 값과 최신 값은 같은 말이 아니라는 것입니다. TTL은 오래된 값이 남는 시간을 제한하는 안전망이고, 캐시 무효화는 데이터가 바뀐 사실을 아는 애플리케이션이 더 일찍 캐시를 비우는 동작입니다.

만료 순간에 요청이 몰리면

인기 상품의 캐시가 끝난 바로 그 순간 요청 1,000개가 들어오면 모두가 동시에 ‘캐시 없음’을 보고 DB로 갈 수 있습니다. 이를 캐시 스탬피드라고 부릅니다. 캐시를 붙였는데 오히려 원본 DB가 순간적으로 더 바빠지는 경우입니다.

한 요청만 DB를 읽어 캐시를 채우고 나머지는 잠시 기다리게 하거나, TTL에 작은 무작위 차이를 두고, 갱신 직전의 값을 짧게 더 제공하는 방법으로 몰림을 줄일 수 있습니다.

데모에서는 실제 부하를 만들지 않고 같은 순간 들어온 요청 10개를 비교합니다. 보호가 없으면 10개 모두 DB를 읽지만, 한 요청만 캐시를 채우게 하면 DB 읽기는 1회이고 나머지 9개는 잠시 기다립니다. 표시되는 숫자는 이 규칙을 설명하기 위한 시뮬레이션이며 실제 서버 측정값은 아닙니다.

장점은 세 가지만 확인하면 됩니다

  • 자주 읽는 데이터에 더 빠르게 응답할 수 있습니다.
  • 같은 요청이 원본 DB에 반복되는 것을 줄입니다.
  • TTL로 캐시가 유지되는 시간을 제한할 수 있습니다.

캐시를 비우고 요청을 몰아 보세요

두 번만 눌러보기

상품 정보를 불러오면 어디서 올까요?

1 처음에는 DB에서 읽어요.2 같은 데이터를 다시 읽어요.3 Redis가 바로 응답해요.
웹 서비스상품 정보 요청
먼저 확인Redis 캐시아직 비어 있음
캐시에 없을 때만원본 DB상품 데이터 보관

응답 시간은 원리를 보여주기 위한 예시이며 실제 측정값이 아닙니다.

이번 요청 결과

아직 요청하지 않았어요.버튼을 누르면 첫 요청과 캐시 요청의 차이를 보여드립니다.
전체 요청0버튼을 누른 횟수
원본 DB 읽기0캐시가 없을 때만
Redis 캐시 적중0DB 요청을 줄인 횟수

한 단계 더 · 오래된 값

DB 가격이 바뀌면 캐시는 어떻게 될까요?

빠른 응답이 항상 최신 응답은 아닙니다. 원본과 캐시를 나란히 비교해 보세요.

원본 DB · 최신 값89,000원DB 쓰기 0
Redis 캐시 · 저장된 값비어 있음첫 조회 뒤 채워집니다
준비먼저 Redis에 상품을 저장합니다.위의 첫 요청과 같은 흐름으로 DB를 읽고 캐시를 채웁니다.

이 실험은 cache-aside에서 자주 쓰는 “DB 갱신 성공 후 캐시 삭제” 흐름을 단순화했습니다. 실제 서비스에서는 DB 쓰기와 캐시 삭제 중 하나가 실패할 때를 위한 재시도나 이벤트 처리도 필요합니다.

한 단계 더 · 요청 몰림

TTL이 끝난 순간 요청 10개가 들어오면?

모두가 같은 캐시 미스를 보면 원본 DB를 동시에 읽는 캐시 스탬피드가 생길 수 있습니다.

실제 부하 측정이 아닌 원리 비교입니다. 운영 환경에서는 잠금, single-flight, TTL 무작위 분산, 만료 전 갱신 같은 방법을 상황에 맞게 선택합니다.

장점 세 가지만

Redis를 캐시로 쓰는 이유

01반복 조회가 빨라져요.

자주 찾는 값을 메모리에서 바로 읽습니다.

02DB가 덜 바빠져요.

같은 데이터를 매번 원본에서 읽지 않습니다.

03오래된 값은 지워져요.

TTL이 끝나거나 데이터가 바뀌면 캐시를 비웁니다.

캐시 확인없으면 DB 조회Redis에 잠시 저장변경되면 캐시 무효화
교육용 시뮬레이션입니다.

실제 Redis 서버나 데이터베이스에 연결하지 않습니다. 운영 환경의 응답 속도와 동시 요청 결과는 네트워크, 데이터 크기, 서버 구성과 캐시 적중률에 따라 달라집니다.

참고: Redis 공식 Cache-aside 안내 · TTL 명령 문서

데모만 따로 보려면 전체 화면으로 열기.

별도의 명령을 입력할 필요가 없습니다.

1. 캐시 적중과 TTL

  1. 상품 정보 불러오기를 누릅니다.
  2. DB에서 읽은 값이 Redis에 저장되는 것을 확인합니다.
  3. 같은 상품 다시 불러오기를 누릅니다.
  4. Redis 캐시 적중과 줄어든 DB 읽기 횟수를 확인합니다.

10초가 지나면 캐시가 자동으로 사라집니다. 다시 버튼을 누르면 DB에서 값을 가져와 캐시를 채우는 흐름이 반복됩니다.

2. 가격 변경과 캐시 무효화

  1. 실험용 캐시를 채웁니다.
  2. 원본 DB의 가격만 79,000원으로 바꿉니다.
  3. Redis에서 다시 읽어 이전 89,000원이 빠르게 나오는지 확인합니다.
  4. 오래된 캐시를 지우고 다시 불러 새 가격으로 채웁니다.

3. 만료 순간의 요청 몰림

동시 요청 10개 비교하기를 누릅니다. 모든 요청이 DB로 가는 경우와 한 요청만 DB를 읽는 경우의 차이를 나란히 보여줍니다.

일부러 뺀 기능

Redis에는 문자열, 해시, 리스트, 셋, 랭킹, 메시지 처리 등 많은 기능이 있습니다. 이번 데모에서는 모든 명령을 소개하지 않습니다. 처음 보는 사람도 흐름을 잃지 않도록 반복 읽기, TTL, 오래된 값 무효화, 만료 순간의 요청 몰림이라는 하나의 캐시 이야기만 다룹니다. 자료 구조와 명령 문법은 별도의 Redis 명령 실습장이 더 어울리는 주제라 이 화면에는 섞지 않았습니다.

캐시가 비는 순간이 가장 위험합니다

캐시를 붙이면 원본의 부담이 줄어든다는 설명은 캐시가 채워져 있을 때의 이야기입니다. 비어 있는 순간에는 반대가 됩니다.

인기 있는 값 하나의 유효 기간이 끝나는 순간을 생각해 보면 이렇습니다. 그 값을 찾는 요청이 초당 수백 개 들어오고 있었다면, 만료된 직후 그 요청들이 전부 동시에 원본으로 갑니다. 캐시가 있기 전에는 요청이 고르게 퍼져 있었는데, 캐시가 생기면서 오히려 한 시점에 몰리는 모양이 만들어진 것입니다.

서버를 다시 띄운 직후에도 같은 일이 생깁니다. 캐시가 통째로 비어 있으므로 한동안 모든 요청이 원본까지 갑니다. 평소 부하를 감당하도록 맞춰 둔 원본이 이 구간을 못 버티고 넘어가는 경우가 있습니다.

대응은 몇 가지가 있습니다. 같은 키에 대한 요청 중 하나만 원본으로 보내고 나머지는 그 결과를 기다리게 하거나, 유효 기간에 약간의 무작위를 섞어 만료 시점을 흩뜨리거나, 만료 직전에 미리 새 값을 채워 두는 방식입니다. 어느 쪽이든 캐시가 비는 순간을 설계에 포함해야 한다는 점이 공통입니다.

실제 속도는 환경마다 다릅니다

데모에 표시되는 응답 시간은 차이를 설명하기 위한 예시입니다. 실제 속도는 네트워크 거리, 데이터 크기, Redis와 DB 구성, 동시 요청 수와 캐시 적중률에 따라 달라집니다. 이 페이지는 실제 Redis 서버에 연결하지 않는 교육용 시뮬레이션입니다.

덧붙여, 이 데모에서 쓰는 SET user:1 kim 같은 명령이 서버까지 어떻게 겹겹이 포장되어 배달되는지 궁금하다면 네트워크 7계층 랩에서 이어서 눌러볼 수 있습니다.

확인한 자료


관련 글