본문 바로가기

Cloud

AWS - Elastic Cache

★ Elastic Cache

[Redis]

1) RDS와 동일한 방식으로 관계형 데이터베이스를 관리할 수 있음

2) Redis or MemCached와 같은 캐시 기술을 통해 관리

 

Cache?

: 높은 성능과 낮은 지연 시간을 가진 인-메모리 데이터베이스

3) Elastic Cache를 사용하면 읽기 집약적인 워크로드의 부하를 줄이는데 도움이 됨

▷ 일반적인 쿼리가 캐시되어 데이터베이스가 매번 쿼리되지 않는 것, 캐시는 이러한 쿼리의 겨로가를 검색할 때 사용할 수 있음

 

[MemCached]

4) Application의 상태를 Amazon Elastic Cache에 저장해서 Application을 Stateless로 만들어 버린다.

5) RDS와 동일한 장점을 가지므로 AWS는 동일한 유지보수를 수행, 운영체제, 패치, 최적화, 설정, 구성, 모니터링, 장애회복, 백업수행 등...

 

Elastic Cache 사용하면 Application에 중요한 코드를 빠르게 변경할 수 있음

데이터베이스에 쿼리를 전달하기 전에 캐시를 쿼리하여 Application을 변경할 수 있음


Elastic Cache Architecture

우선 Application은 RDS를 접근하기 전에 먼저 Amazon Elastic Cache에 Query를 날립니다.

여기서 쿼리에 대한 결과물이 있다면 Cache Hit가 반환될 것이며 필요한 결과물을 Application에 보내줄 것입니다.

Cache Hit가 발생하게 된다면 RDS를 통한 데이터베이스 접근을 하지 않아도 되기 때문에 효율성이 높아집니다.

 

그러나 Elastic Cache에 쿼리를 날렸을 때에도 원하는 값이 나오지 않을 경우, Cache Miss가 반환됩니다.

이 경우는 Cache에 값이 없는 것이기 때문에 RDS를 통해 데이터베이스에 접근해야하며 원하는 데이터(Output)를 가져와야 합니다.

그리고 여기서 사용한 쿼리는 추후에 다시 사용될 경우 가용성, 효율성을 높이기 위해서 Elastic Cache에 기록해둡니다.

그럴 경우, 동일한 쿼리가 발생하는 다른 Application이나 Instance일 경우 Elastic Cache에 먼저 쿼리를 날려 원하는 Output을 

반환 받을 수 있게 될 것이므로 RDS 데이터베이스에서 부하를 줄이는데 도움을 줄 것입니다.

추가로 데이터를 캐시에도 저장하기 때문에 쿼리에 따른 데이터가 계속 쌓이는 것을 막기 위해서 가장 최신 데이터만 사용하는지

확인하며 지속해서 업데이트를 해줘야 합니다. (= 캐시 무효화 전략)

 


Elastic Cache Architecture2

 

다른 아키텍처로 사용자 세션을 저장해서 Application을 Stateless로 만드는 것입니다.

사용자가 Application의 모든 계정에 로그인하면 Application Elastic Cache에 세션 데이터를 기록합니다.

사용자가 Application의 다른 인스턴스로 리다이렉션 되면 Application은 Elastic Cache에서 직접 세션 캐시를 검색할 수 있습니다.

다음 과정을 통해 사용자는 계속 로그인한 상태로 한 번 더 로그인을 할 필요가 없게 됩니다.

이처럼, 사용자의 세션 데이터를 Elastic Cache에 기록함으로써 Application 상태를 무언가 할 필요가 없는 상태(Stateless)로 만드는 것입니다. (예시에서는 다시 로그인할 필요가 없는 상태 즉, 현재 세션을 이미 Cache에서 가져왔으므로 무언가 할 필요가 없는 상태)

 

 


※ Elastic Cache Type    

Redis MemCached
자동 장애를 조치하는 기능을 합니다.
강화된 견고성을 지닌 다중 AZ를 제공합니다. 
데이터 분할에 다중 노드를 사용(=샤딩)
고가용성, 백업, 복제, 읽기전용 복제본 모두 사용(=RDS) 가용성은 높지 않으며, 복제도 발생하지 않습니다.
기능 복원, 지속성으로 데이터의 내구성 강화 지속적인 캐시도 아니고 기능 복원이나 백업 기능도 없습니다.
읽기 전용 복제본은 읽기 스케일링에 사용되기에 가용성이 높습니다. 다중 스레드 아키텍처로, 몇몇 샤딩과 함께 캐시에서 실행하는
여러 인스턴스가 있습니다.
(데이터를 손실할 수 없는 단순한 분산 캐시)
Cluster Mode: 견고성, 확장성 증대 Cluster Mode: 고성능의 분산 메모리 객체 캐싱 시스템
(단순 캐싱 역할)
메시지 브로커에도 사용되고 데이터베이스로도 사용가능
Default Port: 6379
샤드당 복제수가 정해져있고, 이를 0으로 하면 다중 AZ 옵션이 비활성화되는 것입니다.
전송 중 데이터 암호화로 Redis 인증 기능을 활성화 할 수 있습니다.

 

 


※ 캐싱 전략

: 데이터 캐싱을 할 때 최신 데이터로 일관성을 유지해야하며, 모든 데이터를 캐싱하는 것이 아니라 해야할 데이터만

캐싱하는 것이 안전하고 효율적입니다.

예를 들어, 비즈니스 적으로 데이터의 값이 정말 중요한 경우 그리고 그 값이 매우 빠르게 바뀌거나 할 경우는

캐시 데이터로 쓸 수는 있지만 가능한 안쓰는 것이 좋습니다.

데이터가 천천히 바뀌고 자주 필요한 키가 적을 경우 캐시를 사용하는 것이 좋습니다.

 

데이터 구조가 캐싱 작업을 할 때에도 적합한 지를 체크해야 합니다. 

캐싱에 좋은 데이터 구조는 Key-Value 구조로 원하는 것을 빠르게 얻을 수 있는 구조입니다.

즉, 키 값이 있고 집계 결과로 나오는 Set이 많지 않은 경우가 캐싱하기에 적합한 구조입니다.

 

 

전략

1) Lazy Loading(Cache-Aside, Cache-Populism)

Elastic Cache Architecture

 

기본 캐시 아키텍처로 확인해 봤을때, 우선적으로 캐시 히트가 뜨게 되면 문제가 되지 않습니다.

캐시 전략은 캐시 미스가 뜰 경우에 대해서 정리하는 것입니다.

구조대로 Elastic Cache(Redis, MemCached)에 먼저 요청합니다.   캐시 히트가 발생하면 그대로 데이터를 가지고 오면 됩니다.

하지만 캐시 미스가 뜰 경우 Application은 RDS를 통해 Database에 데이터를 요청합니다.

해당 데이터를 결과값으로 찾아낸 경우 Elastic Cache에 등록합니다.

Elastic Cache에 데이터를 등록함으로써 다른 Application에서도 같은 쿼리를 이용할 경우 Cache에 먼저 접근하여

Cache Hit를 발생시킬 것입니다.

 

 

RDS에서 요청받은 데이터가 없는 경우, 캐싱되지 않아서 매우 효율적입니다.

캐시를 삭제하거나 노드 실패(MemCached)가 발생해도 치명적이지 않다.

캐시를 한 번 예열 해야 하므로 대기 시간은 늘어난다.

 

* MemCached에서는 다중 노드를 사용해서 캐시를 분산

* 예열: 모든 읽기가 RDS로 간 다음에 캐싱되어야 함(즉, RDS에서 데이터베이스에서 Select하고 관련 데이터를 캐시에 등록(캐싱))

 


※ Cache-Miss ★

캐싱-전략 1번 Lazy-Loading/Cache-Aside/Cache-Populism(읽기 최적화)

 

[문제점 - 읽기 패널티]

1) Application에서 Elastic Cache로 3번의 네트워크 호출

ㄱ. Application → RDS 호출 때 발생

ㄴ. RDS → 데이터베이스 조회 작업 할 때 발생

ㄷ. 결과값을 Cache에 등록할 때 발생

 

 사용자 입장에서는 무언가를 읽을 때, 익숙하지 않는 지연이 발생한다.  앞서 3회 네트워크 호출에 따른 지연이 발생하기 때문이다.

 

2) 오래된 데이터일 경우

: 데이터가 RDS에서 업데이트 되어도 Elastic Cache에서는 꼭 업데이트가 잘 되어 있을 보장이 없음

→ 캐시에 오래된 데이터가 남아 있을 경우가 있다.

따라서 최신 데이터가 아니어도 RDS와 캐시에 있는 데이터는 일관성을 유지하는 것이 중요하다. 

 

 

def get_user(user_id):
	# Elastic Cache에 데이터 선 요청
	record = cache.get(user_id)
    
    # Caching이 되어있지 않은 경우
    if record is None: 
    	# RDS를 통해 Database에 접근 (SQL Query) > 1, 2번 네트워크 호출
        record = db.query("Select * from users where id = ?", user_id)
        
        # Elastic Cache에 데이터 입력 > 3번 네트워크 호출 
        cache.set(user_id, record)
        
        return record
	
    else:
    	return record
        

user = get_user(10)

캐싱-전략 2번 Write-Through(라이트 스루)

: 데이터베이스를 수정할 때 먼저 캐시에 쓰기 ★★

- 데이터베이스가 업데이트 될 때, 캐시를 추가하거나 업데이트를 함으로써 일관성을 유지하고 최신화를 하는 것

▷ Write Through를 하는 이뉴는 Elastic Cache를 통해 RDS에 데이터베이스에 데이터를 입력/수정하기 때문

 

캐시에 있는 데이터는 오래된 데이터 일 수 없다.  

왜냐하면 RDS DB 수정할 때 캐시에도 자동으로 변경되기 때문입니다.

하지만 이러한 Write Through 전략에도 패널티가 있다.

 

[문제점 - 쓰기 패널티]

1) 데이터베이스에 데이터를 수정/입력 할 때 발생

- Amazon RDS or Database에 데이터가 업데이트 되거나 추가될 때까지 데이터 누락이 발생(시간적 지연에 따른 누락)

- 데이터가 RDS에 기록되기 전에 Elastic Cache 또는 일반적인 캐시가 필요한 모든 데이터를 갖지 못함

☆ 해결책: Write Through & Lazy-Loading(Cache-Aside) 결합해서 처리

→ Application이 Elastic Cache에서 데이터를 찾지 못하면 RDS에서 Lazy-Loading 하면된다.

 

2) 캐시에 수정/입력 할 때 발생

- RDS에 데이터를 많이 추가할 경우 Elastic Cache에도 많은 데이터가 있지만, 읽히지 않을 가능성도 있음(Cache 이탈 가능성)

▷ 캐시 사이즈가 작을 경우 발생, 캐시에 들어가는 데이터 구조(Key - Value)가 좋지 않을 경우 발생

☆ 해결책: 캐시 구조(Key-Value)를 잘 맞춰준다.  그리고 캐시 사이즈를 확장한다.

 

추가로 사용자 입장에서는 읽기보다는 쓰기에서 속도 지연이 더 발생하다.

 

 

def save_user(user_id, values):
	# Save to DB
    record = db.query("Update users ... where id = ?", user_id)
    
    # cache 입력
    cache.set(uesr_id, record)
    
    return record
    

user = save_user(10, {"name" : "haams"})

- DB 데이터 저장 및 수정

- 캐시에 수정 내용 전달

 

get_user 함수와 save_user 함수를 같이 써서 진행하면 쓰기 패널티 문제를 해결할 수 있다.


캐싱-전략 3번 캐시 제거 & TTL(Time to Leave)

: 캐시에는 제한된 크기가 있다.   캐시 데이터를 제거하기 위해서는 Cache Eviction이라는 방법을 사용하면 된다.

예를 들어, 항목을 캐시에서 명시적으로 삭제하거나 캐시 메모리가 꽉 찼을 경우 사용한다.

주로 LRU 방식을 사용한다. (가장 최근에 사용하지 않은, 또는 가장 적게 사용한 데이터를 지운다.)

 

해당 항목을 TTL로 설정하는 방법 또한 있습니다.

예를 들어, A라는 항목은 5분 동안만 사용한다고 할 경우, 5분 후면 캐시에서 알아서 삭제되어야 합니다.

TTL은 리더보드, 코멘트, 활동, 스트림 등 어떤 종류의 데이터에서도 유용하게 사용됩니다.

 

Application에 따라서 TTL은 짧으면 몇 초에서 길면 며칠까지 설정 가능하며, 자주 요청되는 데이터라면 해당 설정은

캐시 관리에도 매우 효율적일 것입니다.

하지만, 너무 캐시에 데이터가 많고 삭제 빈도도 잦다면, 캐시 사이즈를 확장하는 것도 고려해야할 포인트입니다.

Write-Through 전략을 사용할 때를 제외하고는 나쁘지 않은 전략이며, Application에 적합한 값을 설정하는 것이 중요하다.

 

필요한 데이터에 대해서만 캐싱하는 것이 좋고, 사용자 프로필, 블로그와 같은건 TTL 설정하기에 괜찮은 데이터이지만,

가격 데이터나 은행 계좌 값 등 중요한 데이터일 경우 TTL를 사용하는 것은 좋지 않은 방법입니다.

 


Elastic-Cache Replication에 있어서 Redis에서 할 수 있는 방식은 2가지입니다.

1) Elastic Cache Cluster Mode Disabled(클러스터 모드 비활성화)

: 기본 노드는 1개이며 최대 복제가 5개까지 가능합니다.

1개의 샤드에 노드 복제

 

하나의 샤드 안에 기본 캐시노드는 1개(Primary Node)이며 선택적으로 최대 5개까지 캐시를 복제할 수 있습니다.

기본 노드와 복제본이 있을때, 기본 노드가 실패할 경우 복제본이 대신 진행합니다. 

복제본은 캐시 간에 비동기적으로 처리하며 기본 노드는 읽기와 쓰기에 사용됩니다.

Primary Node가 아닌 다른 노드는 읽기 전용이며, 장애 복구 외에도 읽기 복제본을 활성화하면, Redis용 Elastic Cache에서 읽기 성능을 향상시킬 수 있습니다.

즉, 샤드는 1개, 모든 노드가 Redis Cluster에 있는 데이터를 갖게 됩니다.

▷ 노드 실패가 발생할 경우에도 데이터 손실은 대비할 수 있고 다중 AZ를 활성화 할 수 있습니다.

다중 AZ 장애 조치를 위해 기본값으로 활성화 되어 있습니다. (다중 AZ에 좋음)

 

 

 

2) Cluster Mode 활성화

: 데이터가 여러 샤드로 분할되며 쓰기를 확장할 때 유용합니다.

샤드 1번

샤드 2번

샤드 3번

 

클러스터 활성화 복제인 경우는 기본 아이디어가 데이터의 일부분이 샤드 1번, 샤드 2번, 샤드 3번, ... , 샤드 N번 이런식으로 분할됩니다.

즉, 데이터는 모든 샤드에 걸쳐서 분할되며, 각 샤드는 앞서 설명한 클러스터 비활성화 모드와 똑같이 동작합니다.

데이터가 복제되고 모든 샤드에서 복제된 수를 동일하게 설정합니다.

 

다중 AZ로도 가능하며 기본 값으로 활성화 되어 있습니다.

기본 노드와 복제본 사이에서 장애가 발생했을때, 장애 조치가 가능합니다. 

클러스터당 최대 500개의 노드를 가질 수 있습니다.  즉, 복제본을 만들지 않는다면 단일 마스터에 500개의 샤드를 갖는다는 뜻입니다.

 

복제본을 설정해서 1개의 마스터와 1개의 복제본이 있다면 최대 250개의 샤드를 가지게 됩니다.

마찬가지로 마스터 1개, 복제본으로 가질 수 있는 최대 갯수 5개로 총 6개의 노드로 하나의 샤드를 구성했을 경우, 하나의 샤드에 6개의 노드가 들어있기 때문에 한 클러스터당 최대 500개의 노드를 가질 수 있으므로 (500 / 6)을 한 최대 83개의 샤드를 가질 수 있습니다.(★★)

 

Cluster Mode를 활성화 할 경우, 데이터 샤딩에 진심이며, 쓰기를 확장하고 싶어하고 데이터는 분할될 것입니다.

데이터는 여러 샤드에 걸쳐 분할되며 활성화 모드와 비활성화 모드 차이를 확실히 알아두어야 합니다. ★★

 

(Cluster 활성화) 구조: 1개의 클러스터 ⊃ 최대 83개의 샤드 ⊃ 최대 6개의 노드(Primary Node & Relica) // 노드는 최대 500개

(Cluster 비활성화) 구조: 1개의 클러스터 ⊃ 1개의 샤드 ⊃ 최대 6개의 노드(Primary Node & Replica) // 읽기 성능 향상

클러스터 모드 활성화(Elastic Cache Replication) 클러스터 모드 비활성화(Elastic Cache Relication)
하나의 클러스터 당 최대 500개의 노드를 가짐
마스터 노드의 최대 복제량은 5개이므로 하나의 샤드에 최대 6개의
노드가 발생할 수 있음
따라서 하나의 클러스터에 최대 83개의 샤드를 가질 수 있음
Redis에 샤드 하나만 존재하며 내부적으로도 활성화와 같이
마스터 노드 1개, 최대 복제량 5개까지 운용된다.
모든 데이터가 해당 샤드에 있기 때문에 모든 노드가 Redis Cluster에
있는 데이터를 가진다. (1 Cluster - 1 Shard)
모든 데이터는 모든 샤드에 걸쳐서 분할되며, 데이터가 복제될 때 
모든 샤드에서 복제된 수를 동일하게 가져갑니다.
캐시 간에 비동기적으로 처리하며, 기본 노드가 문제가 발생하면
복제본이 대신 진행합니다. 
장애 복구 기능, 다중 AZ기능, 읽기 복제본 기능 
쓰기 노드를 확장할 때 유용함 읽기 성능 향상에 도움이 됨
 
반응형

'Cloud' 카테고리의 다른 글

AWS - Route53  (0) 2023.02.05
AWS - DNS  (0) 2023.02.04
AWS - Aurora  (0) 2023.01.27
AWS - RDS  (0) 2023.01.25
AWS - ASG(2)  (0) 2023.01.25