Skip to content

6장 분산 캐싱 #1586

Description

@jongfeel

6장 분산 캐싱

분산 캐싱은 마치 분산된 여러 도서관이 하나의 대형 도서관처럼 협력하는 방식과 비슷합니다.
각 도서관(캐시 노드)은 자신만의 자료를 가지고 있지만, 네트워크로 서로 연결되어 있어 필요할 때 함께 작동하며 사용자가 원하는 책(데이터)을 빠르게 찾을 수 있도록 돕습니다.
이렇게 서로 협력하면 다양한 서버와 위치에서 하나의 통합된 데이터 계층처럼 작동합니다.

6.1 캐싱 정의

캐싱은 자주 사용하거나 계산 비용이 많이 드는 데이터를 더 빠르게 접근할 수 있는 위치에 저장하고 관리하는 기술입니다.
캐싱의 주된 목적은 데이터를 가져오는 데 필요한 시간과 리소스를 줄이는 데 있습니다.
이를 위해 데이터를 복사하여 저장하는데, 이 복사본은 원본 데이터가 저장된 위치보다 훨씬 빠르게 접근할 수 있는 곳에 저장합니다.

캐싱의 주요 개념

  • 캐시: 캐시는 자주 접근하는 데이터나 리소스의 복사본을 임시로 저장하는 공간
  • 캐싱된 데이터(cached data): 캐시에 저장된 데이터의 복사본을 의미합니다.
  • 캐시 히트(cache hit): 요청한 데이터가 캐시에 있을 때를 의미합니다.
  • 캐시 미스(cache miss): 이 경우 시스템은 원본 데이터 소스에서 데이터를 가져오고, 이후 빠르게 조회할 수 있도록 해당 데이터를 캐시에 저장합니다.
  • 캐시 제거(eviction): 시스템은 적은 빈도로 사용하거나 최근에 사용하지 않은 데이터를 삭제하여 공간을 확보합니다.

6.1.1 분산 캐싱 정의

분산 캐싱(distributed caching)은 데이터에 더 빠르게 접근할 수 있도록 여러 서버나 노드에 자주 사용하는 정보를 메모리에 분산 저장하는 기술입니다.

분산 캐싱의 핵심 목표는 디스크 기반 저장 시스템에서 데이터를 읽는 데 걸리는 속도 문제를 해결하는 데 있습니다.
여러 노드의 메인 메모리에 캐시를 저장해 두면 디스크 입출력(I/O)으로 지연 없이 자주 사용하는 데이터를 빠르게 가져올 수 있습니다.

6.1.2 분산 캐싱과 일반 캐싱의 차이점

일반 캐싱 분산 캐싱
적용 범위 일반적으로 캐싱은 자주 사용하는 데이터를 단일 시스템 내 로컬 캐시에 저장하고 가져옵니다. 이 캐시는 애플리케이션이나 시스템의 일부로 단일 기기나 서버에 있습니다. 분산 캐싱은 캐싱 개념을 네트워크로 연결된 여러 노드나 서버로 확장한 방식입니다. 분산 캐싱 시스템에서는 캐시가 여러 기기에 분산되어 있으며, 이 노드 간에 캐싱된 데이터를 공유할 수 있습니다.
아키텍처 데이터가 로컬 캐시에 저장되며, 이 캐시는 보통 메모리에 위치합니다. 애플리케이션은 동일한 기기 내에서 실행되기 때문에 해당 캐시에 바로 접근할 수 있습니다. 여러 캐시 노드로 구성된 네트워크를 기반으로 작동합니다. 각 노드는 로컬 캐시를 가질 수 있으며, 노드 간 데이터를 공유하고 교환합니다. 이런 아키텍처는 노드를 추가하여 수평적으로 확장할 수 있도록 설계했습니다.
확장성 단일 서버나 단일 애플리케이션 같은 소규모 환경에 적합합니다. 로컬 환경에서 캐싱만으로도 충분한 성능 향상을 얻을 수 있을 때 효과적으로 작동합니다. 대규모 시스템과 애플리케이션에서 발생하는 성능 문제를 해결하려고 설계했습니다. 특히 여러 노드에서 데이터를 동시에 공유하고 빠르게 접근해야 하는 상황에서 성능과 확장성을 크게 높이는 데 유리합니다.
활용 사례 캐싱은 주로 서버나 애플리케이션에서 성능을 개선하고, 데이터베이스 접근 시간을 줄이며, 자주 사용하는 데이터를 빠르게 불러오는 데 활용합니다. 분산 캐싱은 대규모 데이터 접근이 필요하거나 여러 시스템이 데이터를 공유해야 하는 환경에서 효과적입니다. 대규모 웹 서비스, 분산 데이터베이스, 마이크로서비스 구조에서 자주 사용합니다.
일관성 및 동기화 일반 캐싱을 사용할 때는 캐시의 일관성을 유지하는 작업이 꽤나 단순합니다. 하지만 분산 환경에서는 캐시를 무효화하거나 데이터를 동기화하는 과정이 훨씬 복잡할 수 있습니다. 분산 캐싱 시스템은 각 노드가 동일한 최신 데이터를 공유할 수 있도록 설계됩니다. 이를 위해 노드 간 데이터를 동기화하는 프로토콜과 분산 캐시를 효율적으로 관리하는 전략을 이용하여 데이터 불일치나 캐시 무효화 문제를 해결합니다.

6.1.3 활용 사례

  • 웹 애플리케이션
  • 데이터베이스 쿼리 결과
  • 콘텐츠 전송 네트워크
  • 세션 관리
  • API 응답 캐싱
  • 실시간 분석
  • 메시지 큐

6.1.4 분산 캐싱을 사용할 때 장점

  • 성능 개선
  • 확장 용이성
  • 백엔드 시스템의 부하 감소
  • 장애 허용성
  • 일관된 접근 속도
  • 비용 절감
  • 사용자 경험 향상

6.1.5 분산 캐싱의 한계점

  • 일관성 유지의 어려움
  • 캐시 무효화의 복잡성
  • 설정과 관리의 복잡성
  • 네트워크 부하 문제
  • 캐시 데이터의 오래됨 문제
  • 데이터 분배의 어려움
  • 높은 메모리 사용량
  • 비용
  • 데이터 접근 패턴
  • 쓰기 작업에서 한계

6.2 분산 캐시 설계

6.2.1 요구 사항 정의

기능적 요구 사항

  • put(key, value): 키와 값 쌍을 캐시에 추가
  • get(key): 주어진 키로 해당 값을 조회

비기능적 요구 사항은 다음과 같습니다.

  • 높은 성능
  • 높은 확장성
  • 높은 가용성

6.2.2 설계 과정

캐싱에 필요한 데이터 구조

가장 간단한 구조는 키와 값을 저장할 수 있는 해시 맵(또는 해시 테이블)을 활용하는 것입니다.

캐시 삭제 정책

삽입 순서 기반(접근 시간은 고려하지 않음)
  • 선입선출(First In, First Out, FIFO)
  • 후입선출(Last In, First Out, LIFO)
접근 기반
  • 가장 최근에 사용한 항목 제거(Most Recently Used, MRU)
  • 가장 오래된 항목 제거(Least Recently Used, LRU)
  • 최소 사용 빈도 제거(Least Frequently Used, LFU)

LRU 캐시 설계하기

  • 캐시에는 저장할 수 있는 항목의 수(N)가 정해져 있습니다.
  • 캐시에 항목을 추가하는 작업은 O(1) 시간 안에 처리되어야 합니다.
  • 캐시에서 항목을 삭제하는 작업도 O(1) 시간 안에 처리되어야 합니다.

image

Figure 6.1: A doubly linked list and a HashMap

그림 6-1에서 표현하고 있는 시스템은 읽기와 쓰기 두 가지 작업 흐름으로 구성됩니다.
간단히 설명하자면, 쓰기 작업은 데이터베이스에 직접 저장한다 가정하고 읽기 작업에서는 캐시에 데이터가 없을 때만 새로운 데이터를 추가합니다.

  • 경우의 수 1: 키가 해시 맵에 없을 때입니다. 이런 상황을 캐시 미스가 발생했다고 하는데요. 이때는 새로운 항목을 추가해야 하며, 캐시의 항목 수가 N보다 적은 상태입니다.
  • 경우의 수 2: 키가 해시 맵에 없어서 캐시 미스가 발생했지만, 이번에는 캐시가 이미 가득 찬 상태(N개 항목)입니다.
  • 경우의 수 3: 키가 해시 맵에 이미 있을 때, 즉 기존 항목일 때입니다.

시스템 통합하기

방법 1. 애플리케이션 서버와 캐시를 함께 배치하기

그림 6-2와 같이 애플리케이션 서버가 늘어날 때 캐시 인스턴스도 함께 추가되므로, 시스템 전체 처리 능력을 확장하는 데 적합합니다.

  • 장점: 캐시 조회가 동일한 머신 내에서 프로세스 간 호출로 하기 때문에 속도가 빠릅니다.
  • 한계점: 머신이 다운되면 해당 서버는 캐시가 비어 있는 상태일 것입니다.

image

Figure 6.2: A co-located cache solution

방법 2. 애플리케이션 서버와 독립적으로 구현하기

그림 6-3과 같이 캐시를 애플리케이션 서버와 분리해서 독립적으로 운영되는 서버 클러스터에 배포하는 방식입니다.

  • 장점: 요청 빈도나 동시 처리량이 많아지더라도 확장이 가능합니다. 애플리케이션 서버와 상관없이 독립적으로 확장할 수도 있습니다.
  • 한계점: 캐시 키를 기준으로 데이터를 나누어서 저장해야 할 수도 있습니다. 이때 키가 저장된 서버를 찾으려면 로드 밸런서나 키 검색 테이블 같은 방법을 고려해야 합니다.

image

Figure 6.3: A standalone cache solution

어떤 방법을 선택해야 할까?

Table 6.2 shows some key considerations to help you make an informed decision

서버 통합형 스탠드얼론(standalone)형
성능 요구 사항 캐시 데이터 조회와 애플리케이션 응답 속도가 중요할 때는 네트워크 오버헤드 없이 직접 접근할 수 있는 서버 통합형 캐시가 더 좋을 수 있습니다. 확장성과 높은 처리량이 필요한 상황에서는 독립적으로 확장 가능한 스탠드얼론 캐시가 더 적합한 선택이 될 수 있습니다.
확장성 애플리케이션과 캐시를 함께 확장할 수 있는 상황에 적합하며, 확장성 요구가 지나치게 높지 않을 때 효과적입니다. 캐시를 독립적으로 확장할 수 있어 자원 배분을 세부적으로 조정할 수 있는 환경에서는 더 높은 확장성을 제공합니다.
자원 공유 애플리케이션 서버와 캐시가 자원을 공유하면 메모리와 CPU를 더욱 효율적으로 활용할 수 있습니다. 캐시를 애플리케이션 서버와 분리하면 자원 충돌이 발생하지 않아 대규모 시스템에서 보다 적합합니다.
유연성 설정과 통합 과정이 비교적 간단하지만, 기술 선택과 구성 옵션이 제한적일 수 있습니다. 특정 요구 사항에 따라 캐싱 솔루션을 자유롭게 선택할 수 있으며, 기술을 독립적으로 구성할 수 있다는 점에서 더 많은 유연성을 제공합니다.
의존성 및 독립성 애플리케이션 서버와 연결되어 있어 한쪽에서 문제가 생기거나 수정 사항이 있으면 다른 쪽에 영향을 줄 수 있습니다. 스탠드얼론 캐시는 독립적으로 동작하므로, 특정 구성 요소가 변경되더라도 시스템 전체에 미치는 영향이 상대적으로 작습니다.
운영 복잡성 배포와 관리가 비교적 간단하지만, 캐시를 사용할 때 세부적인 요구 사항을 충족하기 어려울 수 있습니다. 설정과 관리가 좀 더 복잡하지만, 애플리케이션 서버에 영향을 주지 않고 필요에 따라 적절한 방식으로 수정하거나 업데이트할 수 있습니다.
인프라와 비용 애플리케이션 서버와 자원을 공유하기 때문에 인프라 비용이 적게 듭니다. 캐시를 독립적으로 배치해야 하므로 추가 인프라가 필요하여 비용이 증가할 수 있습니다.
네트워크 지연 허용성 네트워크 지연 시간을 줄이는 것이 최우선인 애플리케이션에 적합합니다. 캐시에 접근할 때 약간의 네트워크 지연을 허용할 수 있는 애플리케이션에 적합합니다.

요구 사항에 맞게 설계되었는지 점검하기

비기능적 요구 사항 확인

  • 높은 성능: 모든 연산이 O(1)로 처리되기 때문에 매우 효율적입니다.
  • 높은 확장성: 캐시를 배포하는 서버 수를 늘리고 이를 적절히 샤딩하면, 어떤 요청량이나 동시성에도 대응할 수 있어 확장성 측면에서 적합합니다.
  • 높은 가용성: 한 서버가 다운되면 해당 서버에 저장된 데이터 전체를 잃을 위험이 있습니다.

6.3 대표적인 분산 캐시 솔루션

6.3.1 레디스

레디스는 문자열, 리스트, 집합, 해시 등 다양한 데이터 구조를 지원하는 인 메모리 데이터 저장소입니다.
단순한 저장소 기능을 넘어 데이터를 영구적으로 유지할 수 있는 옵션과 함께 발행·구독 메시징, 트랜잭션, Lua 스크립팅 등 고급 기능도 제공합니다.

활용 사례

  • 웹 애플리케이션 캐싱
  • 실시간 분석
  • 세션 저장소
  • 리더보드 및 카운팅 시스템

확장성

레디스는 데이터를 여러 노드에 나누어 저장하는 샤딩 방식을 이용하여 쉽게 확장할 수 있습니다.

커뮤니티 지원

  • 레디스는 활발한 오픈 소스 커뮤니티와 폭넓은 사용자 기반을 자랑합니다.
  • 탄탄한 문서화와 커뮤니티 지원 덕분에 학습과 문제 해결이 수월합니다.

6.3.2 맴캐시드

맴캐시드는 단순하고 직관적인 키-값 저장소로 메모리 기반 캐싱 솔루션으로 활용합니다.

활용 사례

  • 웹 애플리케이션 캐싱
  • 세션 저장소
  • 데이터베이스 결과 캐싱
  • 단순 키-값 분산 시스템

확장성

  • 맴캐시드는 캐시 클러스터에 노드를 추가하여 수평 확장이 가능하도록 설계했습니다.
  • 일관된 해싱 방식을 이용하여 데이터를 여러 노드에 분산 저장합니다.

커뮤니티 지원

  • 맴캐시드는 신뢰할 수 있는 안정적인 코드를 기반으로 하기에 널리 사용합니다.
  • 사용법이 간단하고 다양한 프로그래밍 언어와 쉽게 통합할 수 있습니다.

6.3.3 레디스와 맴캐시드 중 어떤 것을 선택해야 할까?

  • 사용 목적: 레디스는 다양한 데이터 구조를 지원하기에 활용 범위가 넓습니다. 반면에 맴캐시드는 단순한 키-값 캐싱에서 속도가 빠르고 간단하게 사용할 수 있다는 장점이 있습니다.
  • 데이터 보존 여부: 레디스는 데이터를 영구적으로 저장할 수 있는 옵션이 있어 데이터 보존이 필요한 경우 더 적합합니다. 맴캐시드는 메모리 기반 캐시라서 데이터가 기본적으로 영구 저장되지 않는다는 점을 유의해야 합니다.
  • 다양한 데이터 구조 지원: 레디스는 더 다양한 데이터 구조와 기능을 지원하므로 복잡한 데이터 조작이 필요한 상황에서 더 유연하게 사용할 수 있습니다.
  • 사용 편의성: 맴캐시드는 단순하고 직관적인 설계 덕분에 쉽게 통합하고 운영할 수 있다는 장점이 있습니다. 이와 다르게 레디스는 다양한 기능을 제공하지만, 처음 사용하는 사람들에게는 익숙해지는 데 시간이 좀 더 걸릴 수 있습니다.

Metadata

Metadata

Assignees

Projects

Status
Done

Relationships

None yet

Development

No branches or pull requests

Issue actions