Skip to content

Leesumok/redis-cache-lab

Repository files navigation

Redis Cache Stampede Lab

Spring Boot + MySQL + Redis + k6 + InfluxDB + Grafana로 캐시 미스 전략을 비교하는 실험용 프로젝트입니다.

핵심 비교 대상은 4가지입니다.

  • db-direct: 캐시 없이 MySQL 직조회
  • ttl-jitter: TTL을 랜덤화하지만 같은 키 폭주 자체는 막지 못하는 전략
  • distributed-lock: 캐시 미스 시 Redis 분산 락으로 최초 1개 요청만 DB 조회
  • precache: 만료 전에 캐시를 미리 채워 cache miss 순간 자체를 줄이는 전략

구성

  • 앱 대시보드: http://localhost:8080
  • Grafana: http://localhost:3000/d/cache-stampede-lab
  • InfluxDB: http://localhost:8086
  • MySQL: localhost:3306
  • Redis: localhost:6379

흐름은 아래처럼 나뉩니다.

  • 서비스 조회 대상 DB: MySQL
  • 캐시: Redis
  • 부하 생성: k6
  • 결과 저장: InfluxDB
  • 시각화: Grafana

실행

1. 인프라 실행

docker compose up -d

2. 애플리케이션 실행

./gradlew bootRun

기본 연결 정보:

  • MySQL: cache_lab / root / root
  • Redis: localhost:6379
  • Cache TTL: 30초

주요 환경변수:

  • MYSQL_HOST, MYSQL_PORT, MYSQL_DATABASE, MYSQL_USERNAME, MYSQL_PASSWORD
  • REDIS_HOST, REDIS_PORT
  • DB_SIMULATED_LATENCY_MS
  • CACHE_TTL_SECONDS
  • CACHE_TTL_JITTER_SECONDS

3. Grafana 확인

Grafana datasource와 starter dashboard는 자동 provisioning 됩니다.

  • URL: http://localhost:3000/d/cache-stampede-lab
  • admin: admin
  • password: admin

익명 조회도 켜두었기 때문에 index.html 안 iframe에서도 바로 볼 수 있습니다.

API

조회 API

curl http://localhost:8080/api/db/products/1
curl "http://localhost:8080/api/redis/products/1?mode=ttl-jitter"
curl "http://localhost:8080/api/redis/products/1?mode=distributed-lock"
curl "http://localhost:8080/api/redis/products/1?mode=precache"

캐시 제어 API

curl -X DELETE http://localhost:8080/api/redis/products/1
curl -X DELETE http://localhost:8080/api/redis/products
curl -X POST "http://localhost:8080/api/redis/prewarm?mode=precache&ids=1"
curl -X POST "http://localhost:8080/api/redis/prewarm?mode=ttl-jitter&ids=1,2,3,4,5&ttlSeconds=30&jitterSeconds=12"

k6 실험

1. DB 직조회 1000 burst

k6 run --out influxdb=http://localhost:8086/k6 k6/db-load.js

2. 전략별 단독 실험

MODE=ttl-jitter k6 run --out influxdb=http://localhost:8086/k6 k6/redis-load.js
MODE=distributed-lock k6 run --out influxdb=http://localhost:8086/k6 k6/redis-load.js
MODE=precache k6 run --out influxdb=http://localhost:8086/k6 k6/redis-load.js

redis-load.js는 기본적으로 1000 VU x 1 iteration burst로 동작합니다.

3. 4개 전략 순차 비교

k6 run --out influxdb=http://localhost:8086/k6 k6/compare.js

compare.js는 다음 순서로 실행됩니다.

  1. db-direct
  2. ttl-jitter
  3. distributed-lock
  4. precache

각 구간은 Grafana에서 strategy 태그 기준으로 분리해서 볼 수 있습니다.

4. VUser ramp 비교

MODE=db-direct k6 run --out influxdb=http://localhost:8086/k6 k6/vuser-ramp.js
MODE=ttl-jitter k6 run --out influxdb=http://localhost:8086/k6 k6/vuser-ramp.js
MODE=distributed-lock k6 run --out influxdb=http://localhost:8086/k6 k6/vuser-ramp.js
MODE=precache k6 run --out influxdb=http://localhost:8086/k6 k6/vuser-ramp.js

기본 단계는 10 -> 50 -> 100 -> 200 -> 400 VU입니다.

관찰 포인트

같은 키 1개에 1000건이 동시에 몰릴 때

  • ttl-jitter는 근본 해결책이 아닙니다.
  • 같은 키가 miss 나는 순간의 폭주는 여전히 남습니다.
  • distributed-lock은 최초 1개만 DB를 치고 나머지는 기다린 뒤 캐시를 재사용합니다.
  • precache는 miss 자체를 줄여서 가장 안정적으로 보일 수 있습니다.

Grafana에서 우선 볼 패널

  • p95 latency
  • p99 latency
  • request rate
  • failure rate

이 프로젝트의 starter dashboard는 그 4개 패널을 기본으로 제공합니다.

About

레디스 캐싱전략에 대해 연구하고 실험 해보는 레포지토리입니다.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors