본문 바로가기

server/아키텍쳐

캐시

컴퓨터에서 캐시는 일시적인 데이터 집합으로 데이터 요청 시 해당 데이터의 스토리지에 액세스 하여 가능한 한 빨리 처리 위해 사용된다. 캐시를 사용하면 이전의 검색이나 데이터를 효율적으로 재사용할 수 있다

캐시는 운영 체제, CDN (Content Delivery Networks) 및 DNS를 포함한 네트워킹 계층, 웹 애플리케이션 및 데이터베이스를 포함한 다양한 기술 계층 전반에 걸쳐 적용 및 활용할 수 있다. 캐싱을 사용하여 웹서비스, 게임, 미디어 공유 및 소셜 네트워킹과 같은 읽기가 많은 애플리케이션 워크로드에 대해 지연 시간을 크게 줄이고 IOPS를 개선 할 수 있다.

 

애플리케이션 서버 캐시

서버 요청 계층에 직접 캐시를 배치하면 응답 데이터의 로컬 저장이 가능하다. 서비스에 대한 요청이 있을 때마다 노드는 로컬에 캐시 된 데이터가 있는 경우 신속하게 반환할 수 있다. 캐시에 데이터가 없으면 요청 노드가 디스크에서 데이터를 가져온다. 하나의 요청 계층 노드의 캐시는 메모리(매우 빠름)와 노드의 로컬 디스크(네트워크 스토리지로 이동하는 것보다 빠름) 모두에 위치할 수도 있다.

 

 

캐시를 적용하기에 적합한 데이터

  • 반복적이고 동일한 결과가 나오는 반환값
  • 업데이트가 자주 발생하지 않는 데이터
  • 자주 조회되는 데이터
  • 입력값과 출력 값이 일정한 데이터

(캐싱된 데이터는 데이터 갱신으로 인해 DB와 불일치가 발생할 수 있다. 그렇기 때문에 데이터 Update가 잦게 일어나거나 데이터 불일치 시 비즈니스 로직 상 문제가 발생할 수 있는 기능은 캐싱 대상으로 적합하지 않다.)

 

 

캐시를 여러 노드로 확장하면 어떻게 되는가?

서비스 서버가 여러 노드로 확장된 경우에도 각 노드가 자체 캐시를 호스팅 할 수 있다.  그러나 로드 밸런서가 노드에 요청을 무작위로 분산하면 동일한 요청이 다른 노드로 이동하므로 캐시 누락이 증가한다.  이를 극복하기 위한 두 가지 선택 사항은 global cache와 lcoal cache이다.

 

 

Local Cache

  • 서버마다 캐시를 따로 저장한다.
  • 서버 내에서 작동하기 때문에 속도가 빠르다.
  • but 다른 서버의 캐시를 참조하기 어렵다.
  • 캐시에 저장된 데이터가 변경되는 경우는 아래와 같이 작동한다.
    • 해당 서버를 제외한 모든 peer에 변경 사항 전달
    • All-to-All Replication
    • WAS 인스턴스가 늘어나고, 캐시 저장 데이터 크기가 커지면 전체 서비스의 성능이 저하된다.

 

Global Cache

  • 여러 서버에서 하나의 캐시 서버에 접근하여 참조한다.
  • 별도의 캐시 서버를 이용하기 때문에 서버 간 데이터 공유가 쉽다.
  • but 네트워크 트래픽을 사용해야 하므로 로컬 캐시보다 느리다.
  • 데이터를 분산하여 저장할 수 있다.
    • Replication: 두 개의 이상의 DBMS 시스템을 Mater / Slave로 나눠서 동일한 데이터를 저장하는 방식
    • Sharding: 같은 테이블 스키마를 가진 데이터를 다수의 데이터베이스에 분산하여 저장하는 방법
  • 캐시에 저장된 데이터가 변경되는 경우:
    • 추가적인 작업 필요 없음
    • 서비스 확장으로 WAS 인스턴스가 늘어나고, Cache 데이터 크기가 커질수록 효과적인 이유

 

 

콘텐츠 전송 네트워크 (CDN)

CDN은 많은 양의 정적 미디어를 제공하는 사이트에서 사용되는 일종의 캐시이다. 일반적인 CDN 설정에서 요청은 먼저 CDN에 정적 미디어를 요청한다. CDN을 사용할 수 없는 경우 백엔드 서버에 파일을 쿼리하고 로컬로 캐시 한 다음 요청하는 사용자에게 제공한다

사용하는 시스템이 CDN을 가질 만큼 충분히 크지 않은 경우엔 Nginx와 같은 경량 HTTP 서버를 사용하여 별도의 하위 도메인에서 정적 미디어를 제공하여 향후 전환을 쉽게 할 수 있다.

 

cache invalidation 캐시 무효화

캐시를 데이터베이스와 일관성 있게 유지하려면 약간의 유지 관리가 필요하다. 데이터가 데이터베이스에서 수정되면 캐시의 데이터는 무효화되어야 한다(갱신 or 삭제). 그렇지 않으면 일관되지 않은 데이터로 애플리케이션 동작이 오작동할 수 있다.

이 문제를 해결하는 것을 캐시 무효화라고 한다. 사용되는 세 가지 주요 체계가 있다

 

1. Write-through cache(동시 기록 캐시)

어떤 값을 갱신(write) 해야 하면 캐시(메모리)뿐만 아니라 HDD/SSD와 같은 저장장치에도 값을 쓰는 것을 말한다. 메모리뿐만 아니라 HDD/SSD에도 값을 저장하므로 데이터의 손실이 없으나 매번 HDD/SSD에도 값을 써야 하므로 write속도가 상대적으로 느리다.

 

2. Write-back cache

write-back chace에서는 어떤 값을 경신해야 하면 캐시(메모리)에만 먼저 쓴다. HDD/SSD에는 항상 캐시의 수정 내용이 반영되지 않고 특정 시간/조건마다 반영된다. 이렇게 하면 write에도 빠른 속도를 기대할 수 있으나 HDD/SSD에 바로 값을 경신하지 않으므로 서버에 문제가 생기면 데이터가 손실될 가능성이 있다.

 

3. Write-around cache(No-write allocate 또는 write-no-allocate)

이 policy에선 어떤 데이터를 갱신해야 할 때 메모리(캐시)에는 건너뛰고 바로 HDD/SSD에 값을 저장한다. 캐시는 read요청이 왔을 때 그 값이 캐시에 없으면 HDD/SSD로부터 값을 가져온다. write가 많이 발생하지만 그 값을 다시 읽는 경우가 별로 없을 때 사용한다.

 

 

캐시 제거 정책

다음은 가장 일반적인 캐시 제거 정책 중 일부이다.

  1. FIFO (선입 선출) : 캐시는 이전에 액세스 빈도 또는 횟수에 관계없이 먼저 액세스 한 첫 번째 블록을 제거
  2. LIFO (Last In First Out) : 캐시는 이전에 액세스 빈도 또는 횟수에 관계없이 가장 최근에 액세스 한 블록을 먼저 제거
  3. 가장 최근에 사용한 항목 (LRU) : 가장 최근에 사용한 항목을 가장 늦게 제거
  4. 가장 최근에 사용한 항목 (MRU) : LRU와 달리 가장 최근에 사용한 항목을 먼저 제거
  5. LFU (Least Frequently Used) : 항목이 필요한 빈도를 계산. 자주 사용되지 않는 항목이 먼저 제거
  6. 무작위 교체 (RR) : 후보 항목을 무작위로 선택하고 필요할 때 공간을 확보하기 위해 제거

 


 

 

 

번외 Memcached vs Redis

기본적으로 redis는 memcached의 단점을 보안하고자 만들어짐

공통점

  • redis와 memcached 모두 In-Memory 메모리 기반이다.
  • key-value 형식의 No-sql이다.

Redis

  • 자료구조가 다양 (String, Set, Sorted Set, Hash List, json 등 다양한 자료구조를 제공)
  • 메모리뿐만 아니라 디스크도 사용하기 때문에 데이터 복구 시 유용하다.
  • 싱글 스레드를 사용한다.(v3이후부터 멀티스레드 가능)
  • 제거 정책은 6가지 모두 사용 가능
  • 파티션, 레플리카 지원

Memcached

  • 멀티스레드 아키텍처를 지원한다.
  • Redis 보다 적은 메모리를 요구한다.
  • Memcached는 정적인 데이터 저장에 유리하다. Redis는 Copy-on-Write 방식을 사용하기 때문에 실제 사용하는 메모리보다 더 많은 메모리를 요구한다.
  • 제거 정책은 LRU 알고리즘만 사용
  • 단순 데이터만 사용 가능
  • 파티션(샤딩), 레플리카를 지원하지 않는다.

 

 

2016년도 redis vs memcached 성능 비교표

결론

간단한 문자열 캐시만 필요한 경우 Memcached가 올바른 선택 일 수 있다. 그러나 워크로드가 적더라도 나중에 확장성에 대한 옵션이 필요하다면 Redis의 선택이 더 좋다.

음... 그냥 레디스 쓰자.. 레디스 버전이 올라가면서 전부 다 지원해준다...

 

 

 

참고

https://medium.com/@narengowda/designing-the-caching-system-e42c6938df6a

https://docs.aws.amazon.com/ko_kr/AmazonElastiCache/latest/mem-ug/SelectEngine.html

http://blog.leekyoungil.com/?p=200

https://www.instaclustr.com/redis-vs-memcached/

https://scalegrid.io/blog/redis-vs-memcached-2021-comparison/