카테고리 없음

WIL - 인덱스 -> 캐시 -> Redis

그zi운아이 2025. 8. 17. 22:35

인덱스 → 캐시 → Redis 

한눈에 보기

  • 인덱스: 쿼리 자체를 빠르게 만드는 구조.
  • 캐시: 반복 결과를 메모리에 두고 재사용해 부하/지연을 줄임.
  • Redis: 캐시로도 쓰지만, 자료구조/원자연산/TTL까지 제공하는 인메모리 스토어.

인덱스 — 무엇이고 왜 쓰나

  • 정의: RDB가 찾기/정렬/필터를 빠르게 하려는 자료구조(B+Tree 중심).
  • 핵심 포인트
    • 선택: 선두 컬럼 분포가 좋아야 스캔이 짧아짐.
    • 정렬 흡수: 인덱스 순서와 ORDER BY를 맞추면 filesort 회피.
    • 커버링: 필요한 컬럼이 인덱스 안에 있으면 테이블 접근 생략.

인덱스 설계 요령

  • 복합 인덱스 순서 = 쿼리 의도
    WHERE a=? … ORDER BY b DESC, id DESC → (a, b DESC, id DESC)
  • 카디널리티: BOOLEAN/NULL 등 저카디널리티 선두 금지
  • 범위 조건 주의: 복합 인덱스에서 첫 범위(>, <, BETWEEN, LIKE 'p%') 이후 컬럼 활용 약화.
  • Keyset(Seek) 페이징: 깊은 OFFSET 대신 다음 페이지 시작점으로 탐색.

 

인덱스로 안 끝나는 지점

  • 깊은 페이지(OFFSET 수백~수천)
  • 일부 필터+정렬 조합에서만 비싸게 튀는 케이스
  • JOIN 비용 폭증(드라이빙 테이블 선택 실패 등)
  • 순간 경합(스토리지/락/네트워크)
    → 여기서 캐시의 가치가 생김.

캐시 — 무엇이고 왜 쓰나

  • 정의: 반복 접근 결과를 더 빠른 계층(대개 메모리)에 저장해 재사용.
  • 언제 고려?
    • 읽기 편향·중복 접근이 뚜렷함
    • 강한 순간 일관성이 꼭 필요하진 않음(짧은 지연 허용)
    • 정렬/집계/조인 비용이 큼
  • 효과: 원본(DB·외부 API) 부하 절감, 평균/꼬리 지연 개선, 비용 절감.

캐시 패턴 (Cache-aside 포함, 핵심만)

  • Cache-aside (앱 주도 미스 처리)
    GET cache → Miss → GET DB → SET cache → 응답
    단순·통제 쉬움, 프레임워크 종속 낮음. 대부분의 조회 캐시 기본값.
  • Read-through (캐시가 로더)
    앱은 캐시만 읽고, 미스는 캐시가 직접 원본 로드 후 저장/반환.
    앱 단순하지만 캐시 컴포넌트 의존·운영 복잡도↑.
  • Write-through (동기 쓰기)
    캐시에 먼저 기록, 캐시가 즉시 DB 반영.
    캐시/DB 동기화 쉬움, 대신 쓰기 레이턴시↑.
  • Write-back / Write-behind (지연 쓰기)
    캐시에만 먼저 기록, DB는 비동기/배치 반영.
    쓰기 성능↑, 장애 시 유실·불일치 리스크 관리 필요.
  • Refresh-ahead (선제 갱신)
    만료 전에 백그라운드로 재로딩.
    만료 순간 버스트 완화, 예측 빗나가면 불필요 비용.

실전 기본 조합: Cache-aside(읽기) + Write-around(쓰기 시 DB만 갱신 후 캐시 무효화) — 단순하고 예측 가능.


Redis — 무엇인가(캐시 그 이상)

  • 정의: 인메모리 데이터 스토어. String/Hash/Set/ZSet/Bitmap/HLL/Geo/Stream 등 자료구조 + 원자 연산/TTL 제공.
  • 자주 쓰는 용도
    • 캐시(페이지/목록/상세 결과)
    • 세션/토큰(만료·원자성)
    • 카운팅/레이트리밋(INCR, 슬라이딩 윈도우)
    • 랭킹/피드(ZSet), 가벼운 메시징(Pub/Sub, Streams)

간단 의사결정 가이드

  • 쿼리 자체가 느리다 → 인덱스부터(정렬 포함, 선두 선택도, Seek 페이징)
  • 반복 조회/부하가 문제다 → 캐시(패턴 선택 + 무효화 전략)
  • 세션·카운트·랭킹 등 기능적 요구가 있다 → Redis 자료구조 매칭