캐시 (Cache)

Server

(Update : 2023-02-18)

Language :

개념

자주 사용하는 데이터나 값을 미리 저장해 놓는 임시 저장소

서버나 데이터베이스에 가해지는 부하를 줄이고 성능을 높이기 위해 사용한다.

자주 변경되고 삭제되는 데이터에 적용하면 오히려 성능 저하를 일으킬 수 있다.

기본 동작

  1. 클라이언트가 데이터를 요청하면 캐시에 해당 데이터가 있는지 확인한다.
  2. 캐시에 데이터가 있다면(Cache Hit) 캐싱 데이터를 반환한다.
  3. 캐시에 데이터가 없다면(Cache Miss) 실제 데이터를 가져와서 반환하고 해당 데이터를 캐시에 저장한다.

적용 대상

호출 횟수에 상관 없이 주어진 입력(인자)에 대해 동일한 출력(결과)이 보장된다.

자주 변동되지 않고 반복적으로 호출된다. (ex: 썸네일)

데이터베이스에서 조회하는 시간이 오래 걸린다.

계산이 복잡하여 처리가 오래 걸린다.

캐시 적중률이 높다.

  • 캐시 적중률(Cache Hit Ratio) = 캐시 적중 횟수 / (캐시 적중 횟수 + 캐시 부적중 횟수) x 100
    = 캐시 적중 횟수 / 전체 요청 및 접근 횟수 x 100

종류

Local Cache

서버 내부에 저장한다.

  • 서버 내부에서 동작하기 때문에 속도가 빠르다.
  • 서버 Resource(Memory, Disk)를 사용한다.

서버 간에 데이터를 공유할 수 없다.

  • 분산 서버인 경우 데이터 정합성이 깨지는 문제가 발생할 수 있다.

종류

  • Ehcache, Caffeine

Global Cache

Cache Server를 별도로 사용한다.

서버 간에 데이터를 공유할 수 있다.

  • 네트워크 트래픽이 발생하기 때문에 Local Cache보다 속도가 느리다.

종류

  • Redis, Memcached

CDN (Content Delivery Network), Web Caching

프록시 서버(Proxy Server)를 물리적으로 분산하여 사용자 위치를 기준으로 가장 가까운 프록시 서버에서 캐싱되어 있는 웹 콘텐츠를 제공함으로써 웹 페이지 로드 속도를 높이는 서버 네트워크

트래픽이 각 서버로 분산된다.

고려 사항

일반적으로 캐시는 메모리(RAM)에 저장되기 때문에 무분별하게 저장해버리면 용량 부족 현상이 발생하여 시스템이 다운될 수 있다.

캐시 서버에 장애가 발생하면 트래픽이 데이터베이스로 몰리게 되어 과부하로 인해 데이터베이스가 다운될 수 있다. 캐시 서버가 장애로부터 복구되는 동안 데이터베이스가 버틸 수 있도록 대비해야 한다. (캐시 서버를 계층적으로 구축하기도 한다)

캐시를 언제까지 유지시킬 건지 Expire Time 또는 Time-To-Live(TTL)정책과 삭제 알고리즘을 고려해야 한다.

  • 만료 주기가 너무 짧으면 대규모 트래픽 환경인 경우 Cache Stampede 현상이 발생할 수 있다.
  • Cache Stampede: 부하가 높은 상태에서 캐시가 만료되어 순간적으로 데이터베이스 읽기 작업과 캐시 쓰기 작업이 중복으로 발생하는 현상
  • 만료 주기가 너무 길면 메모리 부족 현상이 발생하거나 데이터 정합성이 깨질 수 있다.

중요한 정보나 민감한 정보는 저장하지 않는다.

Local Cache VS Global Cache

  • 데이터 정합성이 깨져도 비즈니스에 영향이 없는 부분은 Local Cache, 데이터 정합성이 중요한 부분에는 Global Cache를 선택할 수 있다.
  • Cloud 환경(Docker, AWS EC2 등)이라면 JVM Memory를 사용하는 Cache는 적합하지 않을 수 있다.
  • Local Cache를 첫 번째 수준 Cache로 사용하고 Global Cache를 두 번째 수준 Cache로 사용할 수 있다.
  • Local Cache는 Memory를, Global Cache는 네트워크 트래픽을 많이 사용하는 점을 고려하여 하나 이상을 결합해서 사용하면 효율성이 높아질 수 있다.

캐시 읽기 전략 (Read Cache Strategy)

Cache Warming을 미리 수행해두는 편이 좋다.

  • 첫 방문자를 위해 인위적으로 캐시에 미리 데이터를 넣어두는 작업
  • 항상 Cache Hit를 받도록 한다.
  • 이 작업을 해두지 않으면 첫 방문자(트래픽)가 급증할 때 Cache Miss가 대량으로 발생하여 데이터베이스에 큰 부하가 가해질 수 있다. (Thundering Herd)
  • TTL을 적절히 사용하여 Thundering Herd를 방지한다.

반복적인 읽기 작업이 많은 경우에 적합하다.

  • 동일한 쿼리를 반복적으로 수행하는 서비스

Cache Aside (Look Aside) 패턴

가장 일반적인 전략

처리 순서

  1. 요청이 들어오면 서버는 캐시를 우선적으로 확인한다.
  2. 캐시에 데이터가 없으면 데이터베이스를 조회한다.
  3. 데이터베이스에서 조회해온 데이터를 캐시에 저장하고 반환한다.

캐시와 데이터베이스를 분리해서 가용한다.

  • 캐시가 필요한 데이터만 저장할 수 있다.
  • 캐시 장애 대비 구성이 되어 있다.
  • 데이터 정합성 유지 문제가 발생할 수 있다.

Read Through 패턴

데이터 동기화를 라이브러리 또는 캐시 제공자에게 위임한다.

캐시를 통해서 데이터를 읽는다.

  • 직접적인 데이터베이스 접근을 최소화한다.
  • 캐시에 문제가 발생하면 서비스 전체 중단으로 빠질 수 있다.
  • Replication, Cluster 등을 이용하여 캐시 서비스의 가용성을 높여야 한다.

처리 순서

  1. 요청이 들어오면 서버는 캐시에 데이터를 조회한다.
  2. 캐시는 데이터가 없으면 직접 데이터베이스에서 데이터를 조회하여 저장한 후에 반환한다.

캐시 쓰기 전략 (Write Cache Strategy)

자주 사용되지 않는 불필요한 데이터로 인해 리소스가 낭비될 수 있기 때문에 반드시 TTL을 사용하여 정리해야 한다.

읽기 전략인 Read Through 패턴과 같이 사용하면 최신 데이터를 항상 캐시에서 사용할 수 있다.

Write Back (Write Behind) 패턴

데이터를 바로 저장하지 않고 Cache Store에 모아서 배치 스케줄러 작업을 통해 데이터베이스에 저장한다.

쓰기 작업이 많고 읽기 작업이 적은 경우에 적합하다.

처리 순서

  1. 모든 데이터를 캐시에 저장한다.
  2. 일정 주기마다 캐시에 있는 데이터를 데이터베이스에 저장한다.

캐시가 Queue 역할을 겸하여 데이터베이스가 받는 Write 부하를 줄여준다.

캐시에서 장애가 발생하면 데이터를 유실할 수 있다. (데이터 손실 가능성이 높다)

  • Replication, Cluster를 이용하여 캐시 서비스의 가용성을 높여야 한다.

Write Through 패턴

데이터 동기화를 라이브러리 또는 캐시 제공자에게 위임한다.

쓰기 작업과 읽기 작업이 많은 경우에 적합하다.

처리 순서

  1. 모든 데이터를 캐시에 저장한다.
  2. 캐시는 바로 데이터베이스에 저장한다.

쓰기 작업이 두 번 발생한다.

  • Write Back 보다 쓰기 속도가 느리다.
  • 쓰기 작업이 적은 서비스에 적합하다.

데이터 정합성이 안정적이다.

비교

Cache 비교
EhcacheCaffeinRedisMemcached
TypeLocalLocalGlobalGlobal
BaseOff Heap MemoryIn MemoryIn MemoryIn Memory
ThreadThread-safe XThread-safeSingle ThreadMulti Thread
ShareOXOO
JSR-107OORedis Client Redisson?
삭제 알고리즘LRU(Least Recent Used) LFU (Least Frequency Used) FIFO(First In First Out)Window TinyLfu 제거 정책TTL, LRU, LFU, RANDOMTTL, LRU
장점기능이 많다.Local Cache 중 저장, 제거 성능이 가장 좋다.데이터 영구 보존 가능채팅, 실시간 스트리밍, SNS 피드, 서버 상호 통신에 유리간단하다. 빠르다
단점Caffein 대비 성능이 낮다.설정이 번거롭다.단순 캐시 기능만 제공한다.메모리 파편화, 단일 스레드 등 기본 기능을 보강해야 하는 부분이 많음데이터 영구 보존 불가 String만 저장 가능
  • Local Cache(Ehcache, Caffein)는 JVM Memory를 사용하여 Cloud 환경인 경우 배포할 때마다 Cache가 사라진다.
  • Memcached는 다중 스레드이며 빠르다. 값이 최대 1MB인 String만 저장 가능하다. 만료 시간이 최대 30일로 제한되어 있다.
  • Redis는 Memcached보다 더 많은 기능을 지원하고, 대중적이어서 자료가 많다. 다양한 자료구조와 삭제 알고리즘을 사용할 수 있다. Read/Wirte 속도 차이가 거의 없지만 검색 속도는 Redis가 더 빠르다.

Reference

캐시의 모든 것 내용 정리

Cache

스프링부트 Caching 도입하기(Redis, Ehcache)

Redis5 설계하기 총정리

[REDIS] 캐시(Cache) 설계 전략 지침 총정리

Cache 전략

Cache - Redis, EhCache or Caffeine?

캐시(Cache) 적용 패턴 및 관리 전략

민갤

Back-End Developer

백엔드 개발자입니다.