Contents
see List작성일 2025. 11. 30.
Redis 캐싱 전략 - Cache Aside, Write Through, Write Behind
Redis를 활용한 캐싱 전략을 이해하면 애플리케이션 성능을 크게 향상시킬 수 있습니다.
캐싱 전략 비교
| 전략 | 읽기 | 쓰기 | 일관성 |
|---|---|---|---|
| Cache Aside | 캐시 → DB | DB 직접 | 낮음 |
| Write Through | 캐시 | 캐시 + DB 동시 | 높음 |
| Write Behind | 캐시 | 캐시 → 비동기 DB | 중간 |
| Read Through | 캐시 자동 로드 | - | 중간 |
Cache Aside (Lazy Loading)
// 읽기
public User getUser(Long id) {
String key = "user:" + id;
User user = redisTemplate.opsForValue().get(key);
if (user == null) { // Cache Miss
user = userRepository.findById(id);
redisTemplate.opsForValue().set(key, user, Duration.ofHours(1));
}
return user;
}
// 쓰기 (캐시 무효화)
public void updateUser(User user) {
userRepository.save(user);
redisTemplate.delete("user:" + user.getId()); // 캐시 삭제
}Write Through
// 쓰기 시 캐시와 DB 동시 업데이트
@Transactional
public void updateUser(User user) {
userRepository.save(user);
redisTemplate.opsForValue().set("user:" + user.getId(), user);
}Write Behind (Write Back)
// 캐시에 먼저 쓰고 나중에 DB 동기화
public void updateUser(User user) {
redisTemplate.opsForValue().set("user:" + user.getId(), user);
// 비동기로 DB 동기화 (배치 처리)
asyncDbWriter.enqueue(user);
}
// 주기적으로 배치 처리
@Scheduled(fixedRate = 5000)
public void flushToDatabase() {
List<User> users = asyncDbWriter.drainQueue();
userRepository.saveAll(users);
}TTL (Time To Live) 설정
// 고정 TTL
redisTemplate.opsForValue().set(key, value, Duration.ofMinutes(30));
// 조건부 TTL
long ttl = isPopular(id) ? 3600 : 300; // 인기 데이터는 1시간
redisTemplate.expire(key, Duration.ofSeconds(ttl));캐시 Stampede 방지
// 분산 락으로 중복 조회 방지
public User getUserSafe(Long id) {
String key = "user:" + id;
User user = redisTemplate.opsForValue().get(key);
if (user == null) {
String lockKey = "lock:user:" + id;
boolean locked = redisTemplate.opsForValue()
.setIfAbsent(lockKey, "1", Duration.ofSeconds(10));
if (locked) {
try {
user = userRepository.findById(id);
redisTemplate.opsForValue().set(key, user);
} finally {
redisTemplate.delete(lockKey);
}
} else {
Thread.sleep(100); // 대기 후 재시도
return getUserSafe(id);
}
}
return user;
}Spring Cache 통합
@Cacheable(value = "users", key = "#id")
public User getUser(Long id) {
return userRepository.findById(id);
}
@CacheEvict(value = "users", key = "#user.id")
public void updateUser(User user) {
userRepository.save(user);
}
@CachePut(value = "users", key = "#user.id")
public User createUser(User user) {
return userRepository.save(user);
}전략 선택 가이드
- Cache Aside: 읽기 위주, 단순한 구현
- Write Through: 쓰기 일관성 중요
- Write Behind: 쓰기 성능 중요, 약간의 데이터 손실 허용
database
| No | 작성일 | Title |
|---|---|---|
| 2914 | 2026. 05. 30. | PostgreSQL Autovacuum 운영 점검: 테이블 팽창과 느린 쿼리를 막는 VACUUM·ANALYZE 실전 가이드 |
| 2859 | 2026. 05. 22. | PostgreSQL 운영 백업과 PITR 복구 점검: pg_dump, pg_basebackup, WAL 보관 실전 가이드 |
| 2777 | 2026. 05. 14. | MySQL 8.4 LTS 운영 쿼리 튜닝: 실행 계획, 히스토그램, 복합 인덱스 실전 점검법 |
| 2619 | 2026. 04. 26. | PostgreSQL 18 완전 정복: Async I/O, UUIDv7, Temporal 제약 조건 실전 가이드 |
| 2536 | 2026. 04. 18. | pgvector + PostgreSQL 벡터 검색 완전 정복 — 설치부터 RAG 시스템 구축까지 |
| 2493 | 2026. 04. 14. | PostgreSQL 17 핵심 기능 완벽 가이드: JSON_TABLE, 쿼리 최적화, 벡터 검색 통합 |
| 2472 | 2026. 04. 13. | PostgreSQL 18 신기능 완벽 가이드: 비동기 I/O, UUIDv7, Index Skip Scan |
| 2452 | 2026. 04. 12. | PostgreSQL 17 + pgvector로 구축하는 AI 시맨틱 검색 시스템 |
| 2428 | 2026. 04. 11. | PostgreSQL 17 SQL/JSON 함수 완벽 가이드 |
| 2392 | 2026. 04. 09. | PostgreSQL 17 쿼리 최적화 실전 가이드 - B-Tree 개선, JSON_TABLE, VACUUM 튜닝 |