Redis 캐시 전략

ramong2·2025년 6월 22일

캐시 전략(Cache Strategy)이란?

캐시는 자주 조회되는 데이터를 빠르게 제공하기 위해 메모리에 저장해두는 기술이다.
Redis는 대표적인 인메모리 캐시 서버로 활용되며, 캐시 전략을 잘 설계하면 DB 부하를 줄이고 응답 속도를 획기적으로 높일 수 있다.

1. 왜 캐시 전략이 필요한가?

  • 캐시 히트율(Cache Hit Ratio)를 높이기 위해
  • 최신성 vs 성능 균형 맞추기
  • 오래된 데이터 정리(만료처리) 정책 필요
  • 일관성 문제를 해결해야 함 (DB와 Redis 간)

2. 주요 캐시 전략 4가지

1. Cache Aside (Lazy Loading)

- 필요한 순간에 캐시에 데이터를 올리는 전략. 가장 일반적이고 널리 쓰입니다.			
  • 읽기
    Redis에서 조회 → 없으면
    DB에서 조회 후 Redis에 저장
  • 쓰기
    DB에 먼저 저장 → Redis 값 삭제 or 갱신

✅ 장점: 데이터 정합성 ↑
❌ 단점: 캐시가 매번 비어있으면 초기 속도 ↓

2. Write Through

- DB에 쓸 때마다 캐시에도 무조건 같이 쓰는 방식
  • 쓰기
    DB 저장 → Redis 저장
  • 읽기
    Redis에서 조회 (항상 최신)

✅ 장점: 캐시가 항상 최신 상태
❌ 단점: 쓰기 트래픽이 많으면 Redis에 부하 큼

3. Write Behind (Write Back)

- 캐시에 먼저 쓰고, 일정 시간/조건마다 DB에 저장
  • 고성능이 요구되는 경우 사용
  • Redis가 장애나면 데이터 유실 가능성 있음

✅ 장점: 쓰기 부하 ↓
❌ 단점: 복잡함, 데이터 유실 리스크

4. Read Through

- 애플리케이션이 Redis만 바라보고, Redis가 DB를 조회해서 채움 (Spring에서 많이 쓰이지는 않음)

3. 캐시 무효화 정책 (만료 정책)

Redis는 캐시를 자동으로 지울 수 있는 만료(Expiration) 기능을 제공한다.

1. TTL(Time To Live): 특정 시간이 지나면 삭제됨
2. LRU (Least Recently Used): 가장 안 쓰인 키부터 삭제
3. LFU (Least Frequently Used): 사용 횟수 적은 키부터 삭제
4. noeviction: 메모리 초과 시 새 값 저장 실패

일반적으로는 TTL + LRU 조합을 많이 사용한다.

# Redis 설정 예시 (redis.conf)
maxmemory 512mb
maxmemory-policy allkeys-lru

4. 캐시와 DB의 정합성 유지 전략

1. 쓰기 시 캐시 삭제 (Cache Aside 방식)

데이터를 DB에 먼저 쓰고,
캐시에 있는 데이터를 삭제(무효화)하는 방식.

동작 흐름

1. 클라이언트가 user:123을 수정 요청함.
2. 애플리케이션은 DB에 있는 user:123을 업데이트.
3. 그리고 캐시에서도 user:123 키를 삭제함 (DEL user:123).
4. 다음에 누군가 user:123을 조회하면?
5. 캐시에 없음 → DB에서 읽어옴 → 다시 캐시에 저장.

✅ 장점

구현이 단순하고 Spring Boot + Redis에서 가장 흔히 사용됨.

⚠️ 단점

DB → 캐시 삭제 사이에 장애나 오류가 나면, 캐시는 구 데이터 그대로 남음 → 정합성 깨질 수 있음.

2. DB 변경 이벤트로 캐시 무효화 (ex. Kafka, Redis Pub/Sub)

DB에 데이터를 변경한 후,
Kafka나 Redis Pub/Sub 같은 메시징 시스템을 통해 캐시 무효화 이벤트를 전달함.

동작 흐름

1. user:123 수정됨 → DB에 저장
2. Kafka나 Redis Pub/Sub으로 user:123 캐시 무효화 이벤트 발행
3. 캐시 서버를 구독 중인 서비스들이 user:123 캐시를 삭제

✅ 장점

여러 서비스 간 캐시 정합성을 유지하기에 좋음
캐시 무효화를 비동기로 처리해서 메인 로직에 영향 없음

⚠️ 단점

Kafka, Redis Pub/Sub 등 인프라 구성 필요

3. 메시지 유실 시 캐시 무효화 실패 가능성

캐시 키에 버전(version)을 붙여서, 데이터가 변경될 때마다 버전을 증가시켜 아예 새로운 키를 사용함.

동작 흐름
1. 유저 정보 최초 저장: 캐시 키 → user:123:ver1
2. 유저가 이름을 바꿨다면?
- DB에 저장 완료
- 키 버전 증가 → user:123:ver2 로 새로 캐싱
3. 이후 요청은 ver2를 읽음
4. ver1은 TTL로 사라짐 (혹은 나중에 수동 삭제)

✅ 장점

캐시 일관성 걱정이 거의 없음 (버전 바뀌면 완전 다른 키로 접근하니까!)
동시에 여러 버전 캐시를 유지할 수도 있음

⚠️ 단점

캐시 메모리 낭비 (이전 버전이 남아있을 수 있음)
키 관리 복잡도 증가
클라이언트가 버전 관리까지 신경 써야 하는 경우가 있음


요약 정리

전략설명주 사용처
Cache Aside조회 시 캐시 없으면 DB 조회 후 저장거의 모든 경우 (기본 전략)
Write ThroughDB 저장 시 Redis도 같이 저장최신 데이터 보장이 중요한 경우
Write BehindRedis 먼저 쓰고 나중에 DB 저장초고속 처리 필요, 비동기 가능할 때
Read ThroughRedis가 DB 조회 및 저장 수행외부 라이브러리 캐시 연동 시

전략설명장점단점
Cache Aside (쓰기 시 삭제)DB에 쓰고 캐시 삭제구현 쉬움, 많이 씀삭제 실패 시 정합성 깨짐
이벤트 기반 무효화Kafka 등으로 캐시 삭제 이벤트 전파여러 서버에 적용 가능, 비동기인프라 필요, 메시지 유실 위험
버전 기반 키user:123:ver1ver2 키 변경으로 무효화강력한 정합성, 캐시 충돌 없음키 관리 복잡, 메모리 낭비

0개의 댓글