개요
이번에 ElastiCache와 관련한 하나의 에픽을 마무리하게 되었다. AWS 셀프 서비스를 위해서 작업에 집중했는데, 본격적인 사내 개발자 사용자 가이드와 안내 문서를 작성하기에 앞서 캐시와 Redis, ElastiCache, 더 나아가 Redis > Valkey 엔진별 특성/ 마이그레이션 내용을 정확히 공부하고자, 블로그 글을 통해 정리해보려고 한다.
그래서 다음과 같은 순서로 글을 쭉 작성하며 정리할 예정!
- 캐싱 개념 | Redis & ElastiCache
- Python으로 통신하면서 단일 노드 ElastiCache 실습해보기
- 클러스터 모드의 ElastiCache 사용하면서 구조 파악하기
- Redis, Valkey 각 엔진을 생성하고, 성능 및 비용 비교하기
- Redis, Valkey 엔진별 차이점 파악하기
이번 포스팅은 첫 번째 단계로, 일단 캐싱과 Redis, ElastiCache에 대해 이해해보려 한다.
1. 메모리와 캐시

캐시는 자주 접근하는 데이터를 빠르게 제공하기 위해 임시 저장소에 보관하는 방법이다. 데이터를 매번 원본 저장소(RDB와 같은 디스크)에서 가져오면 네트워크 통신, 디스크 I/O 등의 비용이 발생한다. 이를 줄이기 위해서 조금 더 빠른 저장소에 데이터 사본을 저장해두고, 요청시 바로 꺼내쓴다.
1.1 우리가 캐시 이야기를 하면 보통 Redis를 바로 떠올리게 되는데, 그 이유는 뭘까?
먼저 로컬 캐시와 원격 캐시의 차이를 살펴보자.
웹 애플리케이션 서버에 직접 캐시를 저장해서 로컬 캐시로 사용하면, 비교적 구현이 쉽고 빠르며, 작은 작업에서는 상당한 개선 효과를 볼 수 있다. 우선 외부 I/O 통신이 없기 때문에 응답 속도가 훨씬 빠르다.
근래의 서비스들은 고가용성을 위해 동일한 서버를 2대 이상 운영하는 경우가 많다. 이때, 로컬 캐시를 이용하면 각 서버 간 데이터 정합성 문제를 일으킬 수 있다.

자주 변화하지 않는 데이터에 대한 잦은 조회는 로컬 캐시를 사용하는 것이 좋다. 각 서버 간 데이터를 실시간으로 완벽히 동기화하는 것이 요구된다면 데이터 최신화를 위한 Redis를 사용한다. [Pay Tech : 분산 시스템에서 로컬 캐시 활용하기]
1.2 캐시 주요 지표
- Cache Hit Ratio
- 요청 중 캐시에서 바로 응답한 비율이다. 하나의 호출 결과를 여러 요청 또는 작업에 사용할 수 있을 경우 사용하는 게 좋다. 각 요청에서 종속 서비스에 대해 고유한 쿼리를 실행하고, 요청 별로 결과값이 달라진다면 캐시 히트 적중률이 낮으므로, 캐시를 통해 얻을 수 있는 이점이 적다.
- Latency
- 요청에서 응답까지 걸린 시간을 의미한다. 캐시 히트를 통해 응답을 받는다면 응답 지연 시간은 당연히 작은 값을 띈다. 캐시 미스가 많이 나면, 응답 지연 시간은 늘어난다. 이러한 경우에는 캐시 미스 경로 최적화 등을 고려할 수 있다.
- 예컨대, AWS에서는 ElastiCache Valkey 엔진에 대해 SuccessfuleWriteRequestLatency와 같은 지표를 제공한다. 이 메트릭은 1분 간격으로 성공적으로 실행된 모든 쓰기 요청을 처리하는데 걸리는 시간을 의미한다.
- 읽어볼 자료: aws valkey latency metric
- Evictions
- 캐시는 데이터의 복사본이므로, 캐시 메모리가 부족해지면 삭제 후 나중에 다시 캐시하는 등의 작업을 수행한다. Redis에서는 Evictions 설정을 통해, 캐싱된 데이터의 크기가 메모리 크기를 초과할 때, 키를 제거하는 정책을 지정할 수 있다.
- Expiration이랑 헷갈리면 안된다! Expired는 TTL 만료로 자연 삭제된 것이고, Evictions는 메모리 부족으로 인해 정책에 따라 강제로 제거된 키를 의미한다.
rate(redis_evicted_keys_total[5m]) # 메모리 초과로 인해 삭제된 키를 5분마다 측정해서 통계
rate(redis_expired_keys_total[5m]) # TTL 만료로 인해 삭제된 키를 5분마다 측정해서 통계
1.3 캐싱 전략
캐시를 이용함에 있어서 주의 깊게 다뤄야 하는 것은 바로 데이터 정합성(캐시 일관성) 문제다. 앞서 Hit Ratio에서 언급한 것처럼, 어떤 종속 서비스에 대해서 하나의 호출 결과를 여러 요청 또는 작업에 활용할 수 있는 경우에 캐시를 쓰는 것이 좋다.
시간이 지나면서 캐싱된 데이터는 source(DB)와의 일관성이 점점 떨어진다. (cdn에서 invalidation을 하는 이유)
따라서, 원본 데이터의 변경률과 데이터 캐싱을 잘 관리해서 데이터 정합성 문제를 일으키지 않으려면 이러한 캐싱 전략이 중요하다.
캐싱 전략에는 3 가지 패턴이 있다.
- 캐시 읽기 전략(Read Cache Strategy)
- Cache-aside(Lazy Loading)
- Read-through
- 캐시 쓰기 전략(Wrirte Cachce Strategy)
- Write-through
- Write-arount
- Write-back (Write-behid)
대부분의 서비스는 Read - Write 조합을 활용한다. 캐싱 전략은 여기서 깊이 있게 다루기 보다는, 따로 정리해볼 예정이다.
2. Redis(Remote Dictionary Server)
레디스는 메모리 기반의 Key-Value 데이터 저장소다. Table 구조로 데이터가 저장되는 RDBMS와 달리, 비관계형 구조로서 데이터를 단순히 키밸류 쌍으로 저장한다.
- In-memory: 데이터를 디스크가 아니라 메인 메모리(RAM)에 저장하기에, 지연 시간이 훨씬 짧고 처리량이 높다.
- Remote Data Storage이기에, 여러 서버에서 같은 데이터를 공유할 수 있다.
- 다양한 자료구조를 지원한다. (String, Set, Hashes, List...)
- 쓰기 성능 증대를 위한 클라이언트 측 샤딩을 지원한다.
- Sharding: 같은 테이블 스키마를 가진 데이터(row)를 다수의 db에 분산해서 저장한다.
- 레디스는 기본적으로 싱글 스레드로 수행되기 때문에, 안정적인 인프라를 구축하기 위해서는 Replication 구조가 필요하다.
3. ElastiCache 살펴보기

Cluster Mode
노드는 캐시 엔진을 실행하는 서버다. 클러스터는 이러한 노드들을 모아놓은 그룹으로, 전체 캐시 시스템이다. 노드는 Primary Node와 Replica Node로 나뉘는데, 보통 Primary Node는 쓰기 전용, Replica Node는 읽기 전용으로 사용된다. 노드는 독립적으로 데이터를 가지고 있고(하나의 독립적인 인스턴스), 필요한 경우 다른 노드들과 통신한다.
하나의 샤드는 Primary Node와 Replica Node로 구성된다. Replica Node는 FailOver를 위해 Primary Node를 복제하여 대체되기도 한다. 샤드 수를 늘려서 처리량(Throughput)과 저장 용량을 증가할 수 있다. 또한, 여러 개의 Primary Node를 통해 읽기/쓰기를 분산하여 병렬 처리를 통한 이점을 얻을 수 있다.

Multi AZ(Availability Zone)
고가용성(HA) 확보를 위해 여러 Zone에 노드를 분산하는 방식이다. Primary Node와 Replica Node를 서로 다른 Zone에 배치하여, AZ 장애가 발생했을 때 대응 체계를 마련한다.
열심히 공부했던 것들이 스터디에서만 빛을 발하는 슬픈 현실;ㅠ 일단 이번에 Redis, Valkey 업무를 맡으면서 이쪽은 아예 정복을 해야겠다는 다짐을 했다. 캐쉬 이야기 2탄도 곧 작성해보겠다.
'DevOps > AWS' 카테고리의 다른 글
| [AWS] CloudWatch 비용 숨바꼭질 : per metric-month (0) | 2024.12.19 |
|---|---|
| [AWS] AWS 하나의 LB로 여러 서비스 운영하기 (0) | 2024.05.22 |
| [AWS] public & private subnet 분리로 서버 운영하기 (2) | 2024.04.07 |
| [AWS] AWS CLI 설정 및 활용하기 (0) | 2024.03.24 |
| [AWS] Serverless에 대해서 & AWS LAMBDA (2) | 2023.03.29 |
