본문 바로가기
Redis

서비스 속도를 높이는 캐시 레이어

by 이상한나라의개발자 2023. 12. 11.

캐싱(Caching)

  • Cache : 성능 향상을 위해 값을 복사해놓은 임시 기억 장치
  • Cache에 복사본을 저장해 놓고 읽음으로서 속도가 느린 장치로의 접근 횟수를 줄임
  • Cache의 데이터는 원본이 아니며 언제든 사라질 수 있음
  • 캐시 적중 (Cache Hit) : 캐시에 접근해 데이터를 발견함
  • 캐시 미스 (Cache Miss) : 캐시에 접근했으나 데이터를 발견 못함
  • 캐시 삭제 정책 (Eviction Policy) : 캐시의 데이터 공간 확보를 위해 저장된 데이터 삭제
  • 캐시 전략 : 환경에 따라 캐시 운영 방식을 선택할 수 있음 ( Cache-Aside, Write-Through...)

 

캐시

 

캐싱 전략 

 

Cache-Aside(Lazy Loading)

 

  • 항상 캐시를 먼저 체크하고, 없으면 원본(ex:db) 에서 읽어온 후에 캐시에 저장함 가장 많이 쓰이는 전략
  • 장점 : 필요한 데이터만 캐시에 저장되고, Cache Miss가 있어도 치명적이지 않음
  • 단점 : 최초 접근이 느림, 업데이트 주기가 일정하지 않기 때문에 캐시가 최신 데이터가 아닐 수 있음

 

Cache-Aside(Lazy Loading)

 

 

Write-Through

 

  • 데이터를 쓸 때 항상 캐시를 업데이트하여 최신 상태를 유지함
  • 장점 : 캐시가 항상 동기화 되어 있어 데이터가 최신이다.
  • 단점 자주 사용하지 않는 데이터도 캐시되고, 쓰기 지연시간이 증가한다.

 

Write-Through

 

 

Write-Back

 

  • 데이터를 캐시에만 쓰고, 캐시의 데이터를 일정 주기로 DB에 업데이트
  • 장점 : 쓰기가 많은 경우 DB 부하를 줄일 수 있음
  • 단점 : 캐시가 DB에 쓰기 전에 장애가 생기면 데이터 유실 가능

 

Write-Back

 

데이터 제거 방식

 

  • 캐시에서 어떤 데이터를 언제 제거할 것인가?
  • Expiration : 각 데이터에 TTL(Time-To-Live)을 설정해 시간 기반으로 삭제
  • Eviction Algorithm : 공간을 확보해야 할 경우 어떤 데이터를 삭제할지 결정하는 방식
    • LRU (Least Recently Used) : 가장 오랫동안 사용되지 않은 데이터를 삭제
    • LFU (LeastFrequently Used) : 가정 적게 사용된 데이터를 삭제 (최근에 사용되었더라도)
    • FIFO (First In First Out) :  먼저 들어온 데이터가 먼저 삭제되는 형태

 

SpringBoot + Redis를 사용한 캐싱 ( Cache-Aside )

 

캐싱 흐름

 

 

build.gradle 의존성 추가

 

implementation 'org.springframework.boot:spring-boot-starter-data-redis'

 

 

application.yml

 

spring:
  cache:
    type: redis

 

 

Controller 

 

@RestController
@RequiredArgsConstructor
public class RedisCachingController {

    private final RedisCachingService redisCachingService;
    
    @GetMapping("/user/{userId}/profile")
    public ResponseEntity<UserProfile> getUserProfile(@PathVariable("userId") String userId) {
        UserProfile userProfile = redisCachingService.getUserProfile(userId);
        return ResponseEntity.ok(userProfile);
    }
 }

 

 

Service

 

@Service
@RequiredArgsConstructor
public class RedisCachingService {

    private final UserRepository userRepository;
    private final StringRedisTemplate stringRedisTemplate;
    
    @Cacheable(value = "userProfile", key = "#userId")
    public UserProfile getUserProfile(String userId) {
        System.out.println("userId = " + userId);
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        User user = userRepository.findByUserId(userId).orElseThrow(() -> new MemberNotFoundException(userId));
        System.out.println("user = " + user);
        return new UserProfile(user.getUsername(), user.getAge());
    }
 }
 

'Redis' 카테고리의 다른 글

Pub&Sub  (0) 2023.12.11
Redis 리더보드 만들기  (0) 2023.12.11
분산 환경에서 세션 스토어 만들기  (2) 2023.12.11
Redis 설치 및 문법  (1) 2023.12.11
RDBMS & NoSQL & Redis  (0) 2023.12.11