[Daily morning study] AWS ElastiCache와 인메모리 캐싱 아키텍처
#daily morning study
AWS ElastiCache란
ElastiCache는 AWS에서 제공하는 완전 관리형 인메모리 캐싱 서비스다. Redis와 Memcached 두 가지 엔진을 지원하며, 데이터베이스 앞단에 캐시 레이어를 두어 응답 속도를 높이고 DB 부하를 줄이는 데 사용한다.
직접 EC2에 Redis를 설치해 운영하는 방식과 달리, ElastiCache는 패치, 백업, 복제, 장애 조치(Failover) 등을 AWS가 자동으로 처리해준다.
Redis vs Memcached
ElastiCache는 두 가지 엔진을 지원하며, 용도에 따라 선택이 달라진다.
| 항목 | Redis | Memcached |
|---|---|---|
| 데이터 구조 | String, List, Set, Hash, ZSet 등 다양 | String만 지원 |
| 복제 (Replication) | 지원 (Primary-Replica) | 미지원 |
| 영속성 (Persistence) | RDB / AOF 지원 | 미지원 (휘발성) |
| 클러스터 모드 | 지원 (Cluster Mode) | 지원 (단순 수평 확장) |
| Pub/Sub | 지원 | 미지원 |
| 멀티스레드 | 단일 스레드 기반 | 멀티스레드 |
| 주요 사용처 | 세션, 순위표, 분산 락, 캐시 | 단순 오브젝트 캐시 |
실무에서는 대부분 Redis를 선택한다. 기능이 훨씬 풍부하고, 복제와 영속성을 지원하기 때문이다.
ElastiCache for Redis 구성 방식
1. Single Node (단일 노드)
가장 단순한 구성. 하나의 Redis 인스턴스만 운영한다.
- 비용이 낮다
- 장애 시 복구 불가 (SPOF)
- 개발/테스트 환경에 적합
2. Cluster Mode Disabled (복제 그룹)
Primary 노드 1개와 Read Replica 여러 개로 구성된다.
Client ──→ Primary (Write)
├── Replica 1 (Read)
└── Replica 2 (Read)
- 읽기 부하를 분산할 수 있다
- Primary 장애 시 Replica가 자동으로 승격된다 (Automatic Failover)
- 데이터는 단일 샤드에만 저장 (데이터 파티셔닝 없음)
3. Cluster Mode Enabled (클러스터 모드)
데이터를 여러 샤드에 분산 저장한다. 각 샤드는 Primary + Replica 쌍으로 구성된다.
Shard 1: Primary + Replica → slot 0~5460
Shard 2: Primary + Replica → slot 5461~10922
Shard 3: Primary + Replica → slot 10923~16383
Redis는 총 16,384개의 해시 슬롯을 사용한다. 키를 CRC16으로 해시한 뒤 16384로 나눈 나머지를 슬롯 번호로 사용해 어느 샤드에 저장할지 결정한다.
- 대용량 데이터 저장 가능 (수평 확장)
- 쓰기 성능도 분산된다
- 멀티 키 연산에 제약이 생긴다 (같은 슬롯에 있어야 함)
캐싱 전략
ElastiCache를 도입할 때 어떤 캐싱 전략을 쓸지 결정해야 한다.
Cache-Aside (Lazy Loading)
애플리케이션이 직접 캐시를 확인하고, 없으면 DB에서 가져와 캐시에 저장하는 방식이다.
def get_user(user_id):
cached = redis.get(f"user:{user_id}")
if cached:
return json.loads(cached)
user = db.query("SELECT * FROM users WHERE id = %s", user_id)
redis.setex(f"user:{user_id}", 3600, json.dumps(user))
return user
- 실제로 요청된 데이터만 캐시에 올라간다
- 캐시 미스 시 응답 지연이 발생한다 (Cold Start 문제)
- DB와 캐시 간 데이터 불일치가 생길 수 있다
Write-Through
데이터를 DB에 쓸 때 캐시에도 동시에 쓰는 방식이다.
def update_user(user_id, data):
db.update("UPDATE users SET ... WHERE id = %s", user_id)
redis.setex(f"user:{user_id}", 3600, json.dumps(data))
- 캐시 미스가 거의 없다
- 자주 접근하지 않는 데이터도 캐시에 올라간다 (낭비 가능)
Write-Behind (Write-Back)
캐시에 먼저 쓰고, 일정 시간 후 DB에 비동기로 반영하는 방식이다.
- 쓰기 성능이 높다
- 캐시 장애 시 데이터 유실 위험이 있다
TTL과 Eviction Policy
TTL (Time to Live)
캐시 데이터에 만료 시간을 설정해 자동으로 삭제되게 한다.
SET session:abc123 "user_data" EX 1800 # 30분 후 만료
TTL 없이 데이터를 쌓으면 메모리가 가득 차서 장애가 발생할 수 있다.
Eviction Policy
메모리가 가득 찼을 때 어떤 키를 삭제할지 결정하는 정책이다.
| 정책 | 동작 |
|---|---|
noeviction | 메모리 초과 시 에러 반환 |
allkeys-lru | 모든 키 중 LRU 방식으로 삭제 |
volatile-lru | TTL 설정된 키 중 LRU 방식으로 삭제 |
allkeys-lfu | 모든 키 중 LFU 방식으로 삭제 |
allkeys-random | 무작위 삭제 |
volatile-ttl | TTL이 가장 짧은 키를 먼저 삭제 |
캐시 용도라면 allkeys-lru 또는 allkeys-lfu가 일반적으로 적합하다.
ElastiCache와 VPC 구성
ElastiCache는 반드시 VPC 내부에 위치시켜야 하며, 외부에서 직접 접근할 수 없다.
[인터넷]
│
[ALB / EC2 / Lambda] ← Public Subnet or Private Subnet
│
[ElastiCache Subnet Group] ← Private Subnet
│
[RDS / Aurora] ← Private Subnet
- ElastiCache 서브넷 그룹을 생성해 특정 서브넷에 배치한다
- Security Group으로 접근을 허용할 출처를 명시한다 (예: EC2 SG에서만 6379 포트 허용)
- 같은 AZ에 있는 인스턴스에서 접근해야 지연 시간이 줄어든다
Multi-AZ와 Failover
Cluster Mode Disabled 구성에서 Multi-AZ를 활성화하면:
- Primary 노드 장애 감지 시 자동으로 Replica가 Primary로 승격된다
- DNS 엔드포인트가 새로운 Primary를 가리키도록 업데이트된다
- 일반적으로 30초~1분 이내에 복구된다
애플리케이션은 Primary 엔드포인트 하나만 바라보면 되고, Failover는 투명하게 처리된다.
Primary Endpoint: my-cache.abc123.cfg.apne2.cache.amazonaws.com:6379
Cluster Mode Enabled에서는 Configuration Endpoint를 사용한다. 클라이언트가 클러스터 토폴로지를 자동으로 파악한다.
모니터링 지표
CloudWatch에서 ElastiCache의 주요 메트릭을 확인해야 한다.
| 지표 | 설명 |
|---|---|
CacheHits | 캐시에서 응답된 요청 수 |
CacheMisses | 캐시 미스 횟수 |
CacheHitRate | 캐시 히트율 (높을수록 좋다) |
Evictions | 메모리 부족으로 삭제된 키 수 |
FreeableMemory | 사용 가능한 메모리 잔량 |
CurrConnections | 현재 연결 수 |
ReplicationLag | Primary와 Replica 간 복제 지연 |
Evictions가 급증하거나 FreeableMemory가 낮으면 메모리를 증설하거나 Eviction Policy를 조정해야 한다.
실무 적용 시 체크리스트
- 엔진 선택: 단순 키-값 캐시라면 Memcached, 복잡한 자료구조나 Failover가 필요하면 Redis
- 노드 타입 선택:
cache.r7g.*(메모리 최적화),cache.t3.*(개발/테스트) - Multi-AZ 활성화: 프로덕션 환경에서 반드시 설정
- 서브넷 그룹: Private Subnet에 배치하고 Security Group으로 접근 제어
- TTL 설정: 모든 캐시 키에 적절한 TTL을 부여
- Eviction Policy: 캐시 용도라면
allkeys-lru또는allkeys-lfu - 모니터링:
CacheHitRate,Evictions,FreeableMemory알람 설정