AWS 기술 블로그
Amazon ElastiCache Serverless 운영하기
Amazon ElaistCache Serverless는 캐시를 1분 안에 생성하고 애플리케이션 트래픽 패턴에 따라 용량 크기를 즉시 조정할 수 있는 서버리스 옵션이며, 인기 있는 두 가지 오픈 소스 캐싱 솔루션인 오픈 소스 Redis와 Memcached와 호환됩니다. ElastiCache Serverless를 사용하면 용량 계획에 시간을 소모하지 않고도 가장 까다로운 워크로드에 대해 캐시를 운영할 수 있습니다. 즉, 애플리케이션의 메모리, CPU 및 네트워크 리소스 사용률을 지속적으로 모니터링하고, 지원하는 워크로드의 액세스 패턴 변화에 따라 즉시 확장되기 때문에 캐시 계층을 구축할 때 시간과 비용을 절약할 수 있습니다. 참고로 현재(2024년 9월)까지 나온 7.1 이하 버전의 오픈 소스 Redis 기반 ElastiCache는 계속 지원될 예정이며, 2024년 10월부터 Amazon ElastiCache와 Amazon MemoryDB에서 Valkey에 대한 지원이 이뤄지기 시작했습니다. 이와 관련한 자세한 내용은 다음의 블로그와 블로그를 참고하시길 바랍니다.
서버리스 환경은 변화하는 액세스 패턴과 트래픽에 탄력적으로 대응하기 때문에 개발자는 애플리케이션 설계에만 집중하면 됩니다. 다만, 일부 워크로드에서는 서버리스가 탄력적으로 대응하는 속도에 비해 액세스 패턴과 트래픽이 훨씬 더 급격하게 변화할 수 있고 이런 변화에 빠르게 대응하는 것에 어려움을 겪을 수 있습니다. 따라서 모니터링과 운영이 최소화되어 있는 서버리스 환경에서도 안전한 운영과 민첩한 대응을 위해 모니터링과 운영이 작은 부분이지만 필요할 수 있습니다.
본 글에서는 캐시 계층을 활용한 아키텍처와 ElastiCache Serverless의 확장 방식을 살펴보고, 이에 알맞는 모니터링과 운영 방법에 대해 알아보겠습니다.
캐시 계층을 활용한 아키텍처
캐시(Cache)는 일반적으로 일시적인(transient) 특징이 있는 데이터를 저장하는 고속 데이터 계층입니다. “고속”을 비롯해 캐시는 여러가지 장점이 있지만, 아키텍처를 설계하거나 시스템을 운영할 때는 “일시적인”이라는 키워드에 초점을 맞출 필요가 있습니다. 말 그대로 캐시에 저장되는 데이터는 일시적이며, 캐시 계층에 장애가 발생했다면 캐시에 저장한 데이터는 유지되는 것을 보장하지 않습니다. 물론 ElastiCache의 경우 백업 제약을 충족한다면 자동 및 수동 백업을 사용할 수 있으나 백업 시점과 장애 시점 간의 차이가 발생할 수 있습니다. 즉 항상 모든 쓰기를 디스크에 쓰는 것이 언제나 보장되지 않음을 뜻하며 이는 데이터의 내구성이 보장되지 않음과 동일한 의미입니다.
따라서 캐시 계층을 설계할 때는 캐시에 유실 가능한 데이터가 저장하는 것이 아니라면 아래 그림의 아키텍처와 같이 내구성이 보장되는 계층이 필요합니다. 해당 계층은 MySQL, PostgreSQL과 같은 RDBMS 혹은 DynamoDB처럼 다양하게 구성될 수 있으며 일반적으로 기존에 서비스에서 사용하던 데이터 내구성 계층을 활용하게 됩니다.
그림 1 : 캐시와 다양한 데이터 내구성 계층을 활용한 아키텍처 예시
캐시 계층을 구축할 때는 위와 같은 한계로 인해 캐시 계층을 신뢰할만한 하나의 소스(Single Source Of Truth, SSOT)로 사용할 수 없고 따라서 데이터 내구성 계층이 필요함을 이해하고 있어야 합니다. 캐시 계층에 문제가 발생할 수 있다는 것이 이해했다면, 이러한 한계에도 불구하고 캐시 계층을 왜 구축하게 되는지 자연스럽게 의문을 가지게 될 수 있습니다. 엔지니어와 아키텍트는 캐시 계층을 추가적으로 구축 및 운영하는 비용과 다음과 같은 캐시 계층의 장점 사이에서 트레이드 오프를 고려하게 됩니다.
- 위에서 설명한 것처럼 캐시는 고속 데이터 계층입니다. 인메모리로 구성되어 있는 경우가 많기 때문에 마이크로초 단위의 응답 시간을 고려해볼 수 있습니다.
- 짧은 처리 시간으로 인해 높은 처리량을 기대해볼 수 있고 데이터 내구성 계층에 쏠리는 부하를 분산할 수 있습니다.
- 특정 엔진에서는 데이터 내구성 계층에서 구축하는 것보다 더 용이하게 개발자 친화적인 다양한 자료구조(List, Sorted Set, Stream 등)를 활용할 수 있습니다.
- 데이터 내구성 계층을 확장(스케일업, 스케일 아웃)하는 것은 캐시 계층 구축에 비해 상대적으로 난이도와 비용이 높습니다.
캐시 계층으로 인한 트레이드 오프를 고려하고 있거나 이미 캐시 계층을 구축한 상황이라면, 이미 데이터 내구성 계층을 운영하는 비용으로 인해 고통스러운 상황일 가능성이 높습니다. 또한 이런 환경에서 추가적으로 캐시 계층을 운영하는 것은 큰 부담이 될 수 있습니다. 따라서 관리 비용을 줄이고 운영에 도움을 줄 수 있는 AWS 관리형 서비스인 Amazon ElastiCache가 등장하게 되었으며, 여기에서 더 나아가 ElastiCache Serverless가 나오게 되었습니다.
ElastiCache Serverless 확장 방식
ElastiCache Serverless는 위에서도 설명했듯 탄력적으로 확장하는 구조를 가지고 있습니다. 탄력적인 확장을 위해 여러 지표들을 자동으로 추적하고 이에 기반하여 트래픽을 예상하여 확장하는 구조입니다. 물론 대부분의 워크로드에서는 서버리스를 통한 대응이 충분할 수 있지만, 특정 환경에서는 확장 속도에 대한 이해도를 기반으로 조정해야 할 수 있습니다.
ElastiCache Serverless의 확장 방식을 이해하는 두 가지 키워드를 뽑자면 ElastiCache Processing Units(ECPU)와 스토리지입니다. ElastiCache Serverless는 CPU, 메모리, 네트워크와 같은 리소스의 사용률을 지속적으로 추적하며 이를 기반으로 확장하는 구조입니다. 즉, vCPU 시간과 전송된 데이터를 모두 포함하는 단위인 ECPU와 캐시 크기를 결정할 수 있는 스토리지 크기가 확장의 주요 요소이며 실제로 이 두 가지 요소의 최소/최대 제한을 활용하여 확장을 조절하게 됩니다.
ECPU의 경우 기본적으로 단순 GET과 SET 요청을 기반으로 하고 있기 때문에 추가 vCPU 시간이 필요한 복잡한 명령이라면 더 높은 ECPU를 소모하게 됩니다. 다시 말해, 연산이 캐시에 미치는 영향이 크다면 높은 ECPU를 소모하게 되고 이런 ECPU를 기반으로 스케일링 이벤트가 발생할 수 있습니다. 또한 ECPU의 최대 제한을 설정했다면, ECPU 초과 시에 ElastiCache Serverless에서는 지연 시간이 증가하게 되며 이후 요청을 스로틀링(Throttling)하게 될 수 있습니다. 최소 제한의 경우, 이를 너무 작게 설정했다면 급격한 트래픽에 적절히 대응하지 못할 수 있습니다. ECPU는 10~12분마다 2배로 증가시킬 수 있기 때문에 최소 제한을 사전에 적절히 증가시켜두는 것이 중요합니다. 이는 뒤의 파트에서 더 알아보도록 하겠습니다.
스토리지는 캐시에서 사용하고 있는 스토리지 사용량을 기준으로 합니다. 스토리지도 ECPU와 동일하게 추적하며 스케일링 이벤트를 발생시킵니다. 또한 스토리지 최대 제한을 설정했다면, 스토리지 최대 제한에 도달함에 따라 ElastiCache Serverless는 TTL(Time-To-Live)이 설정된 데이터를 LRU 로직을 사용해서 제거하기 시작합니다. 만약 제거할 수 있는 데이터가 없다면 추가 쓰기 요청은 메모리 부족(Out-Of-Memory, OOM) 메시지를 받게 됩니다. 최소 제한의 경우, 확장 이벤트가 발생할 수 있다면 ECPU와 동일하게 적절히 설정하는 것이 필요합니다.
이처럼 간단하게 ElastiCache Serverless를 이해할 때 도움이 되는 ECPU와 스토리지와 최소, 최대 제한에 대해 알아봤습니다. 만약 위와 같은 확장 방식 외에도 ElastiCache Serverless 기저가 되는 컴퓨팅 플랫폼의 동작 방식에도 관심이 있다면 AWS re:Invent 2023의 Introducing Amazon ElasitCache Serverless 영상에서 이를 구체적으로 소개하고 있기 때문에 해당 영상을 참고하시길 바랍니다.
ElastiCache Serverless 운영하기
최대 제한에 대한 알림 설정하기
위의 확장 방식에서 설명한 것처럼 최대 제한을 설정했다면 이에 대한 CloudWatch 알림을 설정하는 것이 필요합니다. 안전한 운영을 위해 사용량이 정점에 이르렀을 때보다 70~80% 사이에 알림 임계 지점을 설정하는 것이 필요하며, 만약 더 급격하게 트래픽 변화가 있는 워크로드라면 더 공격적으로 알람의 임계 지점을 설정하는 것이 필요합니다. ECPU의 경우 ECPUs Consumed(ElastiCacheProcessingUnits) 대시보드(지표)를, 스토리지의 경우 DataStored(BytesUsedForCache) 대시보드(지표)를 기반으로 적절한 알림 임계 지점을 설정할 수 있습니다. 참고로, ECPU의 경우 커맨드 종류별 ECPU에 대한 지표도 제공하고 있기 때문에 어떤 커맨드에서 ECPU를 크게 소모하는지 확인하고 최적화할 수도 있습니다.
Pre-scaling(최소 제한) 활용하기
예측 가능한 사용량 급증에 대비하여 ElastiCache Serverless는 사전 확장을 할 수 있습니다. 이는 최소 제한 설정을 통해 가능합니다. 확장 방식에서 설명한 것처럼 ElastiCache Serverless는 초당 ECPU를 10~12분마다 2배로 늘릴 수 있기 때문에 대부분의 워크로드에서 충분한 수준의 탄력성을 제공하지만, 이 속도를 초과할 것으로 예상된다면 피크 이벤트가 발생하기 최소 60분 전에 최소 제한을 예상되는 피크 초당 ECPU로 설정하는 것을 권장합니다. 다만, 이렇게 최소 제한을 설정하게 되면 실제 사용량이 최소 제한보다 적더라도 해당 제한만큼 요금이 청구되며, 이를 초과하는 사용량에 일반 요금이 부과되게 됩니다.
복제본으로부터 읽기(Read from Replica)를 활용하기
ElastiCache Serverless는 빈 캐시일 때 30K ECPU/초를 지원하며 만약 복제본으로부터 읽기(Read from Replica)를 사용할 경우 최대 90K ECPU/초를 지원합니다. 복제본으로부터 읽기의 경우, 대부분의 클라이언트 라이브러리에서 지원하고 있습니다. 즉, ElastiCache Serverless를 사용하고 있다면 복제본으로부터 읽기를 옵션을 클라이언트에 적용하여 더 높은 초당 ECPU 사용량을 가져갈 수 있습니다.
또한 복제본으로부터 읽기 옵션을 사용할 경우 ElastiCache Serverless에서는 읽기 요청이 클라이언트의 로컬 가용영역으로 보내지기 때문에 지연 시간을 줄일 수 있습니다.
모니터링 시 살펴보면 좋은 지표
최대 제한과 관련한 지표를 기본적으로 모니터링하며 함께 살펴볼 지표들을 간단히 정리하면 다음과 같습니다.
그림 2 : 모니터링 대시보드 예시
Throttled Requests와 Evicted Key Count
확장 방식에서 설명한 것처럼 최대 제한으로 인해 스로틀링과 축출(Eviction)이 발생할 수 있습니다. 특히 스로틀링의 경우 먼저 지연 시간이 증가하고 이후에 발생하게 되기 때문에 지연 시간에 대한 추적도 함께 진행하는 것이 좋습니다. 따라서 Limit에 대한 임계에 대한 알림이 울리고 Throttled Request 혹은 Evicted Key Count가 급증하고 있다면 급격한 트래픽 변화로 인해 최대 제한으로 인한 영향을 받기 시작했다는 의미이므로 최대 제한을 확장해야 할 가능성이 높습니다.
SuccessfulReadRequestLatency와 SuccessfulWriteRequestLatency
ElastiCache Serverless 내부에서의 지연 시간을 의미하는 지표이며, 클라이언트 측의 지연 시간은 포함되지 않습니다. 전반적인 지연 시간이 늘었을 때 해당 지표를 먼저 확인하고 서버 측 지연 시간이 늦어지고 있는지 먼저 확인할 필요가 있습니다. 클라이언트 측 지연 시간을 계측하고 있다면, 해당 지표를 통해 문제를 분류하는 것이 빠른 대응에 도움이 될 수 있습니다.
Cache Hit Rate
Cache Hit Rate 지표는 전반적인 캐시 계층의 성능을 알아볼 수 있는 지표입니다. Cache Hit Rate이 낮다면 캐시 계층이 역할을 적절히 수행하지 못하고 있으며 데이터베이스와 같은 데이터 내구성 계층에 부하가 가고 있음을 의미합니다. 이는 높은 수준의 데이터 최신성(Data freshness)이 필요하지 않음에도 불구하고 TTL이 너무 짧게 설정되어 있어 캐시 미스가 빈번하거나, 캐싱 전략이 적절하지 않아 캐시에서 읽어와야 하는 데이터가 없어 캐시 미스가 빈번한 상황일 수 있습니다.
CurrVolatileItems
TTL이 있는 항목들의 수를 알 수 있는 지표인 CurrVolatileItems는 Cache Stampede 현상을 사전에 모니터링하거나 Thundering Herd 문제를 발견하는 것에 도움을 줄 수 있습니다. 일반적으로 읽기와 관련된 캐싱 전략에서는 특정 키가 만료되는 시점에 캐시에 데이터가 없다면 연결된 서비스들이 데이터 내구성 계층에서 데이터를 읽어와 캐시에 저장하게 됩니다. 그러나 해당 키에 대한 트래픽이 높은 상황에서 키가 만료되어, 동시에 해당 키에 대한 캐싱을 수행하게 된다면 Cache Hit와 Latency는 요동치게 됩니다.
즉, CurrVolatileItems가 급격하게 낮아졌고 동시에 Cache Hit Rate도 낮아졌다면 Cache Stampede 현상이 발생하고 있을 가능성이 높습니다. 반대로 CurrVolatileItems가 급격하게 높아졌고 Cache Hit Rate도 높아졌다면 Cache Stampede 현상이 발생할 수 있는 환경이 아닌지 의심해야 합니다. 특히 해당 현상은 한 개의 Hot Key에서만 발생하는 것이 아니라, 배치 작업을 통해 TTL이 있는 대량의 키를 캐시에 적재하는 경우에도 발생할 수 있으므로 캐시를 활용하는 워크로드가 증가하고 있는 추세라면 해당 지표에 대한 모니터링이 필요할 수 있습니다.
Serverless Cache에 대한 이벤트 확인하기
ElastiCache는 서버리스 캐시와 관련있는 이벤트들을 로깅합니다. 해당 이벤트들을 보기 위해서 AWS 콘솔이나 AWS CLI에서 describe-events 커맨드를 활용해서 볼 수도 있지만, Amazon EventBridge와 Amazon CloudWatch Logs를 활용해서 더 편리하게 모니터링할 수 있습니다. Amazon EventBridge의 Rules를 활용하면 Amazon ElastiCache에서 발생하는 이벤트를 소스로 CloudWatch Logs에 적재할 수 있습니다. 만약 이벤트에 대한 지표가 필요하다면 CloudWatch Logs의 지표 필터(Metric Filter)를 통해 지표로 변경하고 대시보드를 통해 모니터링할 수 있습니다.
그림 3 : aws-cli를 활용한 decribe-events 결과
그림 4 : EventBridge를 소스로 타겟인 CloudWatch Logs에 기록된 이벤트
결론
본 글에서는 캐시 계층에서의 아키텍처, Amazon ElastiCache Serverless의 확장 방식을 알아보고 운영 시 확인해야 하는 부분들까지 살펴봤습니다. 캐시 계층을 구축 및 운영해본 경험과 지식이 적어 용량 계획에 어려움을 겪고 있다면 ElastiCache Serverless를 활용하는 것은 좋은 시작점이 될 수 있습니다. 다만, 캐시 계층 운영은 용도, 원하는 스펙, 액세스 패턴 등 각 워크로드마다 매우 상이하기 때문에 원하는 수준의 캐시 계층을 구성하기까지 반복적으로 개선해 나가야 합니다. 또한 캐시 계층에 장애가 발생했을 때 워크로드의 데이터 내구성 계층에는 어느 정도의 영향이 가고 장애 대응 계획은 어떻게 될지 사전에 준비해야 합니다.
Elasticache Serverless 운영 이외에 모니터링 모범 사례에 관해서는 다음 문서를 참고할 수 있으며, 캐싱 전략에 대한 문서나 트러블 슈팅에 관한 문서도 함께 참고하시길 바랍니다.