tech/database

AWS Elasticache(redis) 내부동작 정리

daniel_lab 2024. 3. 31. 18:06

Overview

새로운 서비스에 AWS Elasticache 를 캐시 데이터베이스로 사용할 예정이어서, Redis와 Elasticache 운영에 필요한 내용들을 정리하려 한다.

레디스 Deployment Architecture

레디스 아키텍처

레디스의 아키텍처는 4가지 타입으로 구분될 수 있다.

  1. 싱글 노드
  2. High Avaliability(HA 구성)
  • primary node, secondary node
  1. Redis Sentinel
  • 2번으로인해 SPF를 방지할 수 있지만, instance down을 감지하지 못하면 의미가 없다. sentinel은 지속적으로 instance가 healthy한지 모니터링하고 발견되면 spinning up하는 역할을 하며, 이외에도 primary 가 다운되면 쿼럼에 기반한 합의알고리즘에 의해 replica중 하나를 primary로 승격시키는 등의 역할을 한다
  1. Redis Cluster
  • 1개의 writer instance 만 있으면 TPS를 올리고 싶거나 키 저장을 더 많이 하고싶다는 요구가 있을때 vertical scaling 을 해야한다
  • Redis Cluster는 분산캐시 개념으로 이를 해결한 것인데, 샤드를 이용한다.
  • 특정 데이터의 키를 저장할때, 키의 데이터를 업데이트 할때, 읽을때 당연하게도 모두 해당키가 최초에 저장된 그 샤드에서 진행되어야 한다. 노드가 늘어날때마다 키가 분리되는 알고리즘은 계속해서 업데이트된다(해시슬롯 컨셉)
  • 어떻게 reader replica는 writer 와 sync 되나? -> 샤드의 write node에 write command가 발생할때 wirte 노드에 적용된 이후 reader replica로 비동기적으로 전송되어 실시간 적용되며 sync된다. (writer가 command를 보내기전에 다운되면 데이터 소실 위험 존재하는것으로 확인된다). 이 방식은 일반적인 경우의 replication이 이루어지는 방식이고, 리더와 writer가 불일치 하거나(lag) 리더 레플리카가 처음으로 setup 될때는 writer가 전체 메모리를 압축된 스냅샷으로(.rdb file) 만들어 전송한다.

Elasticache의 레디스 아키텍처 지원

  1. cluster mode enabled, disabled 할 수 있다
    enabled 하면 위에서 말한 cluster mode 이다(샤드, 레플리카. 샤드에서 primary 와 replica 나뉘고 데이터 동기화는 write command를 비동기적으로 전송하거나 snapshot 전송하거나 하는등으로 맞춘다)
    disabled 하면 redis sentinel 아키텍처이다

참고로.. 레디스는 single thread 이기 때문에 vcpu를 높은것을 사용한다고 해서 성능적으로 향상되는 부분이 거의 없다. 성능향상을 위해선 여러 인스턴스 샤딩을 통한 scale out 해야한다.

Elasticache key sharding

레디스는 모든키가 해시슬롯에 매핑되는 형태로 키를 샤딩한다. 하나의 클러스터 내에서 16384개의 해시슬롯이 존재한다. 샤드가 늘어나면 단순히 해시슬롯의 레인지를 균등하게 나눠갖는 식으로 분배된다

무중단으로 샤드 추가

클러스터 모드에서 1개의 샤드로 시작 후, 샤드 추가가 필요한 경우 horizontal scaling 하는 것이 추천되고 있다. 무중단으로 해당 과정을 제공하므로 부담스럽지 않아 좋아보인다.

Scaling clusters in Redis(Cluster Mode Enabled): AWS Elasticache 공식 도큐먼트
https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/scaling-redis-cluster-mode-enabled.html

샤드를 추가해야하는 환경은 아래와 같다.

  1. CPU or network bottleneck
    다음 metrics 참고하여 판단 가능: CPUUtilization, NetworkBytesIn, NetworkBytesOut, CurrConnections, NewConnections
  2. cluster가 over-scaled 되었을때
    다음 metrics 참고하여 판단 가능: FreeableMemory, SwapUsage, BytesUseForCache, CPU, NetworkByteseIn, Out, CurrConnections
  3. memory pressure
    다음 metrics 참고하여 판단 가능: FreeableMemory, SwapUsage, BytesUseForCache

데이터 백업

Redis의 백업

  1. AOF(Append Only File)
    레디스에서 실행되는 모든 command 는 append only file에 기록된다. 이 로그파일은 디스크에 존재하며 주기적으로 디스크로 flush 되며 쌓인다.
  2. RDB(Relational DataBase Backup File)
    1과는 매우 다른방식으로, 캐시메모리의 현재 상태를 snapshot 으로 만드는 것이다. 이 dump는 file(.rdb)로 만들어진다. rdb가 만들어지는 방법은 레디스의 BGSave 명령어이다. 아무래도 노드의 부하가 있기 때문에, 스냅샷은 reader 노드에서 생성하는것이 좋다

알 수 있듯, RDB가 AOF보다 로딩속도가 당연히더 빠르다. AOF는 모든 커맨드를 리플레이 하는 것이기 때문이다.

Elasticache 백업

elasticache 는 multi-AZ 배포라는 기능이 있는데, 이는 primary 와 secondary replica node를 다른 AZ에 위치시키는 것이다. AZ가 달라서 replication 비용이 꽤 있을 것이라 생각할 수 있으나, 비 동기적으로 low latency inexpensive network 통해서 동기화 시킨다.

multi-az는 AOF보다 여러방면에서 좋은데, primary노드가 갑자기 죽었을때의 reliability 도 좋고 데이터양 측면에서도 좋다. primary가 갑자기 죽을때 replica는 최소한의 replication lag 로 fail over를 한다(copy of entire data 가지고 promoted to primary됨) 이것은 AOF로부터 리빌딩하는속도와 차원이 다르고 reader 는 항상 sync된다.

elasticache 는 rdb백업을 수동 혹은 자동으로 스냅샷으로 마련할 수 있다. 이 rdb 파일은 s3 버킷에 저장된다. 이것으로 데이터가 동일한 클러스터를 생성하는 등이 가능하다.

rdb 백업을 마련하는 방식에는 fork 방식과 forkless 방식이 있다. fork 방식은 알다시피 redis 프로세스를 fork 하여 당시의 메모리를 그대로 카피한 자식 process를 생성하고, 이 프로세스로 하여금 db에 스냅샷데이터를 백업하는 역할을 맡기는 것이다. 기존 데이터를 그대로 복사하므로 데이터의 메모리 사용률이 50%가 넘었을 경우 해당 방식의 백업은 실패하게 된다.

하지만 꼭 50%의 여유메모리가 있지 않더라도 데이터백업을 할 수 있는 방안이 있는데, 이것이 forkless 방식이다. forkless 방식은 메모리를 좀더 효율적으로 사용해서 백업하는것이다.

원리는 백업 프로세스가 생성된 후 원본 프로세스의 메모리페이지들을 그대로 백업하고 수정되거나 추가되는 메모리페이지의 경우엔 원본프로세스가 따로 메모리페이지를 카피해서 다른곳에서 관리하도록 하는 것이다. 즉, 백업프로세스는 백업이 시작한 시점의 메모리페이지들만 백업하게되고, 수정되거나 추가되는 페이지가 발생할경우 redis 원래 프로세스에서 다른곳에다가 해당 메모리를 관리하기 시작함으로써 여유메모리가 크게 필요하지 않게된다.

하지만 경우에 따라선 이 방법도 여유메모리가 많이 필요할 수 있는데, 그 이유는 백업과정중 수많은 메모리페이지가 수정될 경우 메모리 내에서 수정되는 메모리페이지 들의 복사가 이루어지면서 여유메모리를 빠르게 잡아먹을 수 있기 때문이다. 따라서, fork 방식이든 forkless 방식이든 최악의 경우 50% 이상의 여유메모리가 필요하게 되는 상황은 나올 수 있다는 것을 염두에 두어야 한다.

elasticache 에서는 이처럼 백업을 염두에두고 여유메모리를 강제적으로 할당할 수 있는 파라미터를 제공하는데 이것이 reserved-memory, reserved-memory-percent 이다. 이런 파라미터를 통해 확보된 메모리공간은 백업시의 안정성을 높여줄 수 있다.

Directives

directive란 redis의 동작을 설정할 수 있는 파라미터들을 의미한다. redis에선 redis.conf 파일 내용에 파라미터와 그 값들이 적히면서 설정되는데, maxmemory, maxmemory-policy, maxclients.. 등등이 있다.

eviction policy 설정할 수 있다. maxmemory 도달했을때 어떤 데이터를 추방할지에 관한 것이다. 디폴트로는 volatile-lru가 사용되는데 ttl 설정된 데이터중 가장 나중에 사용된 데이터를 추방하는 정책이다. ttl 데이터가 없는경우엔 no-eviction 으로 동작한다. 즉, 추가적인 insert가 모두 reject 된다

elasticache 에서는 파라미터그룹 이라는 것으로 해당 설정을 할 수 있게하는데, 만약 default parameter group을 사용해버리면 runtime에서 설정을 변경할 수 있는 것을 할 수 없게 되어 꼭 default 파라미터그룹은 사용하지 않는 것이 좋다.

Redis Data structures

각각의 데이터셋의 동작방식과 time complexity는 redis의 공식 document 참고하면 https://redis.io/docs/data-types/ 참고하면 자세히 알 수 있다

참고

AWS re:Invent 2021 - Deep dive on Amazon ElastiCache for Redis
https://www.youtube.com/watch?v=QEKDpToureQ
AWS document: ElastiCache cluster
https://docs.aws.amazon.com/AmazonElastiCache/latest/red-ug/Clusters.html
Redis Concepts and their correlation with AWS ElastiCache - Part 1
https://medium.com/@sonamjournals/redis-concepts-and-their-correlation-to-aws-elasticache-part-1-3be7fc18da92

'tech > database' 카테고리의 다른 글

[MySQL] InnoDB 스토리지 엔진 아키텍처  (0) 2024.09.15
AWS Elasticache vs MemoryDB 비교  (0) 2024.05.31
apache lucene 내부구조  (0) 2023.10.22
dynamodb 내부구조  (0) 2023.10.08
AWS Kinesis Data Stream 내부구조  (0) 2023.10.07