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 |
|---|---|---|
| 2114 | 2026. 02. 11. | PostgreSQL 17 신기능 완전 정리 |
| 2113 | 2026. 02. 11. | pgvector로 구축하는 벡터 데이터베이스 |
| 2112 | 2026. 02. 11. | Supabase 실전 활용 가이드: PostgreSQL의 새로운 패러다임 |
| 2090 | 2026. 01. 13. | mariadb(mysql) vs Oracle vs PostgreSQL: 종합 비교 가이드 |
| 2003 | 2025. 11. 30. | Oracle Hint 사용법 - 옵티마이저 제어하기 |
| 2002 | 2025. 11. 30. | Connection Pool 설정 가이드 - HikariCP |
| 2001 | 2025. 11. 30. | 데이터베이스 백업과 복구 전략 |
| 2000 | 2025. 11. 30. | MongoDB 기초 - Document DB 시작하기 |
| 1999 | 2025. 11. 30. | Redis 캐싱 전략 - Cache Aside, Write Through, Write Behind |
| 1998 | 2025. 11. 30. | 트랜잭션 격리 수준 이해하기 |