Memcached 메모리 캐시 시스템의 원리와 활용

NoSQL 데이터베이스 개요

NoSQL은 "Not Only SQL"을 의미하며, 전통적인 관계형 데이터베이스(RDBMS) 외의 다양한 데이터 저장 방식을 포괄하는 용어다. 주요 유형으로는 다음과 같은 것들이 있다:

  • Key-Value Store: 단순한 키-값 구조로 빠른 접근이 특징. 예: Redis, Memcached
  • Document Store: JSON, BSON 등의 문서 형식을 사용. 예: MongoDB, CouchDB
  • Column-Family Store: 대용량 데이터 처리에 최적화. 예: HBase, Cassandra
  • Graph Database: 노드와 엣지 기반의 복잡한 관계 표현에 강점. 예: Neo4j
  • Time Series Database: 시계열 데이터 처리 전문. 예: InfluxDB, Prometheus

Memcached란?

Memcached는 오픈소스 기반의 고성능 분산 메모리 캐싱 시스템으로, 동적 웹 애플리케이션의 데이터베이스 부하를 줄이는 데 사용된다. 데이터를 RAM 상에 키-값 형태로 저장함으로써 반복적인 DB 조회를 방지하고 응답 속도를 크게 향상시킨다. 서버 프로세스는 C 언어로 작성되었으며, 클라이언트는 다양한 언어로 구현 가능하다.

단, 메모리 기반 시스템이므로 재시작 시 모든 캐시가 소실되며, 영속성(Persistence) 기능은 제공하지 않는다.

Redis와의 주요 차이점

항목 Redis Memcached
지원 자료구조 문자열, 해시, 리스트, 집합, 정렬집합 등 키-값 (단순 문자열)
데이터 영속화 지원 (RDB, AOF) 미지원
고가용성 Redis Cluster, Sentinel 지원 클라이언트 수준에서 구현 필요
최대 값 크기 512MB 1MB
메모리 관리 동적 할당, 조각화 가능성 있음 Slab Allocator로 사전 할당하여 효율적 관리
멀티스레딩 v6 이전까지 싱글스레드 멀티스레드 지원 (CPU 활용 우수)
QPS 성능 약 10만 약 60만
과거 데이터 정리 배경 스레드에서 삭제 접근 시 확인 후 무효화 (Lazy Expiration)
수평 확장 Redis Cluster로 지원 내부 미지원, 클라이언트에서 해시 기반 분산

핵심 동작 메커니즘

1. Slab 기반 메모리 할당

Memcached는 메모리 조각화를 방지하기 위해 Slab Allocator를 사용한다. 전체 메모리는 고정 크기의 Page(기본 1MB)로 나뉘고, 각 Page는 동일한 크기의 Chunk로 분할된다. 서로 다른 크기의 Chunk는 별도의 Slab Class로 그룹화된다.

예를 들어, 100바이트 데이터는 96바이트보다 큰 첫 번째 Chunk(예: 128바이트)에 저장되어 소량의 공간 낭비가 발생할 수 있다. 이러한 크기 증가는 기본적으로 1.25의 Growth Factor에 따라 결정된다.

slab class   1: chunk size        96
slab class   2: chunk size       120
slab class   3: chunk size       150
...

2. 지연 만료 (Lazy Expiration)

데이터의 TTL(Time-To-Live)이 지나도 즉시 삭제되지 않는다. 해당 키에 접근했을 때 비로소 만료 여부를 확인하고, 만료된 항목은 유효하지 않다고 판단한 후 새 데이터로 덮어쓸 수 있도록 한다.

3. LRU (Least Recently Used)

메모리가 부족해질 경우, 가장 오랫동안 사용되지 않은 데이터를 제거하여 새로운 항목을 위한 공간을 확보한다. 그러나 -M 옵션 사용 시 LRU를 비활성화하고 메모리 고갈 시 오류를 발생시킬 수 있다.

4. 클러스터링 아키텍처

Memcached 자체는 노드 간 통신을 하지 않으며, 클러스터링은 클라이언트 주도(Client-side Sharding) 방식으로 이루어진다. 일반적으로 키에 대한 해시 값을 계산하여 어떤 서버에 저장할지 결정한다. 일관된 해시(Consistent Hashing) 기법을 사용하면 노드 추가/제거 시 리해싱의 영향을 최소화할 수 있다.

설치 및 실행

Ubuntu/Debian 계열 기준 설치 절차:

# 의존성 설치
apt update && apt -y install gcc make libevent-dev

# 소스 다운로드 및 컴파일
tar -xf memcached-1.6.20.tar.gz
cd memcached-1.6.20
./configure --prefix=/apps/memcached
make && make install

# 심볼릭 링크 생성
ln -s /apps/memcached/bin/memcached /usr/local/bin/

시스템 서비스 등록 예시 (/lib/systemd/system/memcached.service):

[Unit]
Description=Memcached Server
After=network.target

[Service]
User=memcached
ExecStart=/usr/local/bin/memcached -m 100 -c 10240 -u memcached
Restart=always

[Install]
WantedBy=multi-user.target

서비스 시작:

systemctl daemon-reload
systemctl start memcached
systemctl enable memcached

주요 실행 옵션

  • -u: 실행 사용자 지정 (root 금지)
  • -p: 포트 설정 (기본 11211)
  • -m: 할당 메모리(MB)
  • -c: 최대 동시 연결 수
  • -f: Slab 사이즈 증가 배율
  • -d: 데몬 모드 실행
  • -v[v]: 로그 출력 레벨
  • -U 0: UDP 비활성화

기본 명령어 사용법

Telnet 또는 nc를 통해 직접 프로토콜 테스트 가능:

telnet localhost 11211

저장 (set/add/replace)

set mykey 0 60 5
hello
STORED
  • mykey: 키 이름
  • 0: flags (사용자 정의 비트 플래그)
  • 60: 만료 시간(초)
  • 5: 값의 바이트 수

조회 (get)

get mykey
VALUE mykey 0 5
hello
END

삭제 (delete)

delete mykey
DELETED

전체 비우기 (flush_all)

flush_all
OK

모니터링 도구

libmemcached-tools 설치 시 제공되는 유틸리티:

apt install libmemcached-tools

# 상태 확인
memcstat --servers=localhost

# 핑 테스트
memcping --servers=localhost

# 통계 정보 추출 예시
echo "stats" | nc localhost 11211 | grep -i "cmd_set\|get_hits"

사용 사례

Memcached는 다음 시나리오에서 효과적이다:

  • 매우 높은 QPS가 요구되는 환경
  • 간단한 키-값 조회 중심 애플리케이션
  • 대규모 세션 저장소
  • 정적 콘텐츠 또는 API 응답 캐싱
  • 영속성이 필요 없는 일시적 데이터 보관

태그: Memcached NoSQL Key-Value Store Caching Slab Allocator

6월 15일 21:13에 게시됨