Redis 프리페치 캐시

Redis 프리페치 캐시 (Prefetch Cache)

참조 데이터를 Redis에 미리 로드해 모든 읽기가 캐시 히트가 되게 하는 패턴입니다.

출처: 공식문서 — Redis prefetch cache

언제 Redis 프리페치 캐시를 쓰는가

첫 요청이 도착하기 전에 참조·마스터 데이터를 캐시에 미리 로드해서, 모든 읽기가 히트가 되고 어떤 요청도 기본 데이터베이스로 폴백되지 않아야 할 때 Redis 프리페치 캐시를 사용합니다.

왜 이 문제가 어려운가

Cache-aside는 콜드 스타트 미스를 보장합니다. 모든 키의 첫 요청은 기본(primary)에 닿고, TTL 만료와 다음 읽기 사이마다 모든 서비스가 느린 백엔드에서 같은 행을 다시 가져옵니다. 규모가 커지면 이는 지연 스파이크와 시스템 오브 레코드에 대한 지속적 읽기 압력을 만듭니다 — 부하 패턴은 트래픽이 가장 높을 때 정확히 최악입니다.

Prefetch는 데이터를 사전에 로드해 이를 해결하지만, 그 나름의 제약이 있습니다. 전체 작업 집합(working set)이 메모리에 맞아야 하고, 진실 원천이 바뀔 때 최신 상태를 유지해야 합니다. 소스 데이터베이스에서 동기화 파이프라인을 구축·유지하는 것은 엔지니어링 비용과 지속적 운영 부담을 더합니다 — 캐시가 유일한 읽기 경로가 되면, 동기화 지연은 신선도(freshness) 문제가 아니라 정확성(correctness) 문제가 됩니다.

이 패턴은 캐시가 미스 시 반응적으로 채워지고 기본(primary)이 항상 폴백으로 사용 가능한 cache-aside와는 구별됩니다. 프리페치에서는 애플리케이션이 읽기 경로에서 캐시를 권위 있는 것으로 가정하고, 미스 시 기본으로 폴백하지 않습니다(그리고 지속적 미스율은 인시던트로 취급합니다). 모든 쓰기가 캐시와 기본을 lock-step으로 작성하는 write-through 캐싱과도 구별됩니다 — 프리페치는 쓰기 경로를 캐시에서 분리하고 별도 동기화 파이프라인이 따라잡게 합니다.

Redis 솔루션에서 기대할 수 있는 것

다음을 할 수 있습니다.

  • 국가 코드·상품 카테고리·번역·구성·기타 참조 테이블에 대해 거의 100%에 가까운 캐시 히트율을 달성합니다.
  • 피크 트래픽에서 조회 중심 요청 경로의 P95 읽기 지연을 1ms 미만으로 유지합니다(즉 요청의 95%가 1ms 이하의 지연).
  • 관리형 CDC 파이프라인(예: Redis Data Integration)이나 Debezium·Kafka·Redis 스트림 앞의 작은 컨슈머로 소스 데이터베이스 변경을 수 초 안에 캐시에 동기화합니다.
  • 기본 데이터베이스에서 모든 참조 데이터 읽기를 떼어내, 전용 읽기 복제본 비용을 피합니다.
  • 배포·재시작 시 캐시를 사전 워밍해 콜드 스타트가 절대 백엔드에 닿지 않게 합니다.
  • 동기화 파이프라인이 멈춰도 항목이 만료되는 긴 안전망 TTL(safety-net TTL)로 메모리를 제한해, 조용한 실패가 영원히 오래된 데이터를 서빙하지 않게 합니다.

Redis가 이 솔루션을 어떻게 지원하는가

실제로 애플리케이션은 시작 시 파이프라인 벌크 쓰기로 전체 작업 집합을 Redis에 한 번 로드하고, 그 후 별도 동기화 워커가 진실 원천이 바뀔 때 Redis를 최신 상태로 유지합니다. 모든 참조 데이터 읽기는 Redis에만 갑니다 — 요청 임계 경로에 기본으로의 폴백 경로가 없습니다.

Redis가 프리페치 캐싱에 잘 맞는 이유가 되는 기능들은 다음과 같습니다.

  • Hashes (HSET, HGETALL)와 네이티브 JSON 문서 (JSON.SET, JSON.GET)가 일반적인 참조 데이터 조회 패턴 — 고정 필드 집합의 ID 키 레코드, 또는 JSONPath로 접근하는 더 풍부한 중첩 문서 — 에 직접 매핑됩니다.
  • 파이프라인HSET 또는 MSET 배치가 초기 벌크 로드를 빠르게 만듭니다 — 수천 개 레코드가 단일 왕복에 로드되어, 애플리케이션이 부팅 후 몇 초 안에 완전히 워밍된 캐시에서 서빙을 시작합니다.
  • EXPIRE가 각 항목에 긴 안전망 TTL을 설정해 동기화 파이프라인이 조용히 멈춰도 메모리가 제한된 상태로 유지됩니다 — 신선도 메커니즘이 아니라 가드레일로서요.
  • SCAN이 서버를 블로킹하지 않고 프리페치된 키스페이스를 순회하므로, 애플리케이션이 캐시 커버리지를 감사하거나, 사용 가능한 ID를 나열하거나, 소스에 대한 주기적 조정 패스(reconciliation pass)를 실행할 수 있습니다.
  • Streams (XADD, XREAD)이 동기화 워커가 재시작 후 알려진 오프셋에서 재개해야 할 때 지속적·재생 가능한 변경 피드를 제공합니다 — Redis를 공급하는 CDC 컨슈머의 표준 패턴입니다.
  • 메모리에서의 서브 밀리초 읽기로 참조 데이터 조회가 플레임 그래프에 절대 나타나지 않습니다. Redis가 이미 세션·레이트 리미팅·cache-aside에 스택에 있다면, 프리페치는 제로 한계 비용으로 같은 인스턴스에서 실행됩니다.

생태계 (Ecosystem)

다음 라이브러리·프레임워크가 Redis 기반 프리페치 캐싱을 지원합니다.

  • Java: 벌크 로드용 시작 CommandLineRunner로 채워진 Spring Cache 추상화(@Cacheable with Redis cache store).
  • Node.js: 프리페치된 JSON 문서의 객체 매핑용 Redis OM.
  • 변경 데이터 캡처(CDC) 파이프라인 — 커스텀 애플리케이션 코드 없이 소스 DB 변경을 Redis로 스트리밍: Redis Enterprise/Redis Cloud용 관계형·NoSQL 소스의 Redis Data Integration (RDI); 오픈소스 Redis용 Debezium + 경량 Redis 컨슈머.
  • API 게이트웨이: Kong 플러그인이 참조 데이터 읽기를 백엔드 서비스를 완전히 우회해 Redis로 직접 라우팅.

나만의 Redis 프리페치 캐시를 만드는 코드 예시

다음 가이드들은 참조 데이터의 기본 저장소 앞에서 간단한 Redis 기반 프리페치 캐시를 만드는 법을 보여줍니다. 각 가이드는 시작 시 레코드를 사전 로드하고, 밀리초 내에 기본 저장소 변경을 Redis에 적용하는 백그라운드 동기화 워커를 실행하며, 소스에 레코드가 추가·갱신·삭제될 때 캐시가 최신 상태로 유지되는 것을 볼 수 있는 실행 가능한 대화형 데모를 포함합니다.

더 알아보기 (Learn more)