캐싱이란
캐싱이란, 캐싱 전략과 삭제 전략에 대해 간단하게 정리한 글입니다.
캐싱이란
캐시 (Cache)란 값을 복사해놓는 임시 기억장치를 말하고. 캐싱(Caching)은 성능 향상을 위해 캐시를 이용하여 데이터를 미리 저장해두고 이를 사용하는 기법을 말한다. 캐싱의 목적은 Cache에 데이터의 복사본을 저장해놓고 이를 읽거나 씀으로써 비교적 읽기/쓰기 비용이 큰 장치로부터 접근횟수를 줄여 비용을 아끼는 것이 주 목적중 하나이다. 이를 통해 속도 최적화나 부하 분산이라는 성능 향상 목표를 달성할 수 있다.
단, Cache의 데이터는 일시적이라는 특징을 가지고 있다. 또한 원본이 아니기 때문에 데이터의 일관성 문제도 신경써야한다.
캐싱의 이유
성능 향상
캐싱을 사용하는 주요한 이유 뭘까 -> 성능 향상 응답속도 개선을 통한 -> 빠른 응답으로 달성 가능 -> 빠른 응답을 하기 위해선 -> 데이터를 빠르게 가져올 수 있어야함. -> 데이터의 연산이 이루어지는 곳과 데이터가 가까운 곳에 위치해야함.
원하는 데이터를 가져오고자 할때 드는 시간적인 비용을 계산할때는 CPU와의 위치적 거리를 생각해야한다.
- 레지스터
- L1, L2 cache
- 작고 비싸다.. 비용적인 제한이 필요 특수한 목적으로
- RAM - 메모리 캐시
- 디스크 SSD, HDD
더 빠르고, 값싸게 데이터를 가져올 수 있다면 캐싱을 사용함. 캐싱이라는 기본 원리를 적용해서 성능향상을 이끌어낼 수 있는 곳에서 어디든지 사용되고 있음.
비용 감소
- 네트워크 지연 감소(요청이 덜 가기 때문에)
- 서버 리소스 사용 감소 (api 호출이 줄어들기 때문)
- 병목 현상 완화
- 서버의 경우 무상태라는 특징을 통해 scale out 하여 확장할 수 있음. 분산이 가능.
- 여러 서버로 트래픽 분산이 가능하지만
- 보통 DB는 scale out이 힘듦. 이때 DB가 병목현상이 됨.
- 이때 캐시를 통해 덜할 수 있음.
캐싱의 종류
캐싱은 캐시 위치와 목적에 따라서 다양한 방식으로 존재할 수 있다.
캐시 위치에 따른 분류
WebBrowser (cache). -> web server
- 웹서버에서 변경을 했는데도, 새로고침해도 변경이 잘안되는 경우
Server(cache) -> server
- 네트워크 지연 감소
- 1시간마다 갱신되는 데이터. 1시간 안에는 동일한 데이터를 받게됨. 이때 일정 시간동안만의 캐싱을 함.
Server(cache) -> server
- DB도 동일한 쿼리에 대해서 캐싱할 수 있음.
운용방식에 따른 분류
캐시 전략: 환경에 따라 적합한 캐시 운영방식을 선택할 수 있다.(Cache-Aside, Write-Through)
Cache-Aside (Lazy Loading)
- 항상 캐시를 먼저 체크하고, 없으면 원본에서 읽어온 후 캐시에 저장하는 방식.
- 장점:
- 필요한 데이터만 캐시에 저장되고, (자주 사용되는 데이터의 경우 성능 향상)
- Cache Miss가 있어도 치명적이지 않음. -> 새로 받아오면 됨.
- 단점:
- 최초 접근은 느리다. 최초 접근은 Cache Miss가 나므로. 거의 모든 최초 접근은 원본데이터를 가져옴.
- 업데이트 주기가 일정하지 않기 때문에 캐시가 최신데이터가 아닐 수 있음.
Write-Through
- 데이터를 write할때 항상 캐시에 먼저 업데이트하고, 최신상태를 유지하는 방식.
- 장점:
- 캐시가 항상 동기화되어 있기 때문에 데이터가 최신이다. 데이터 일관성 보장
- 단점:
- 자주 사용하지 않는 데이터도 캐시된다.
- 캐시에 저장하는 과정을 거치다보니 쓰기 지연시간이 증가함.
Write-Back
- 데이터를 캐시에만 쓰고, 캐시의 데이터를 일정 주기로 DB에 업데이트하는 방식
- 장점:
- 쓰기가 많은 경우 DB 부하를 줄일 수 있음.
- 단점:
- 캐시가 DB에 쓰이기 전에 장애가 나서 캐시 데이터가 날아가면, 데이터 유실될 수 있음.
쓰기 부하를 줄여야하는 상황. 데이터 유실이 되더라도 심각성이 낮은 성격의 환경
- 로그 데이터
캐시 삭제 방식
캐시도 저장공간이기 때문에 한정된 자원 공간을 가질 수 밖에 없음. 즉 무한정 늘릴 수 있는 저장공간이 아니기때문에 적절하게 캐시내의 데이터를 삭제해주어야하는데, 이때 캐시가 효율적으로 운용될 수 있도록 캐시 적중률을 많이 떨어뜨리지 않는 방식으로 삭제를 진행하는 것이 좋음.
캐시의 저장 공간을 확보하기 위해 어떤 데이터를 우선적으로 삭제할 것이냐에 대한 내용이다. 이와 관련해서 여러 캐시 삭제 정책들이 존재한다.
캐시 삭제 정책 (Eviction Policy): 캐시의 데이터 공간 확보를 위해 저장된 데이터를 삭제하는 방식.
캐시 전략 | 설명 | 기준 |
---|---|---|
TTL (Time to Live) | 설정된 시간만큼 데이터가 캐시에 존재하고, 시간이 지나면 삭제됨 | 시간 |
LRU (Least Recently Used) | 가장 오래 사용되지 않은 데이터를 우선 삭제 | 가장 오래된 사용 시점 |
LFU (Least Frequently Used) | 가장 적게 사용된 데이터를 삭제, 사용 횟수 기준으로 판단 | 사용 빈도 |
FIFO (First In First Out) | 먼저 들어온 데이터를 먼저 삭제, 큐(Queue) 구조처럼 동작 | 삽입 순서 |
Spring에서 캐시 활용
직접 Redis의 opreation을 이용하여 캐시를 적용할 수도 있고, Spring의 기능을 통해서 캐싱을 구현할 수 있음.
Redis호출 캐시 로직 추가
redisTemplate 를 가지고 존재하다면 get, 없으면 set을 통해서 사용 가능함.
Spring의 @Cacheable
사용
Spring에서 자체적으로 제공하는 캐시 기능이 존재. Spring 에서는 캐시의 추상화를 제공함.
CacheManager를 통해 캐시 인터페이스를 구현(다양한 캐시 구현체가 존재.) 메소드에 캐시를 손쉽게 적용할 수 있음. @Cacheable
- 이 메서드의 인자값을 key로해서 반환값을 value로 캐싱이됨.
Annotation | description |
---|---|
@Cacheable | 메소드에 캐시를 적용한다. Cache-Aside 패턴으로 동작 |
@CachePut | 메소드의 리턴값에 캐시를 설정함. |
@CacheEvict | 메소드의 키값을 기반으로 캐시를 삭제함. |
어떤 것을 써야할까?
- spring에서 제공하는 기능을 사용하면 서비스코드에 부가적 관심사를 어노테이션을 대체해서 사용할 수 있기때문에 가독성이 높아질 수 잇음.
- 만일 반환값이 Object라면 redis에 변환하는 로직을 직접 처리해줘야하는데 스프링에서는 이를 대신 진행해줌.