AWS - 26 [ DynamoDB ]

_Block·2022년 10월 9일
0

AWS

목록 보기
27/27
post-thumbnail

🍊 DynamoDB 기본

NoSQL로 람다와 같이 서버가 따로 없는 서버리스 DB입니다.

전통적인 애플리케이션은 클라이언트를 통해 EBL에 요청을 하고 ASG로 관리되는 EC2그룹이 해당 요청을 처리하게 됩니다.

이후 처리할 떄에는 데이터를 어딘가에 보관을 하던가, 아니면 데이터를 어디서 가져오게 되는데 이는 RDS를 사용한다고 가정하겠습니다.

이러한 시스템 설계 방향은 문제없이 작동될 것 입니다.

  • 또한 이후로 대부분 수직적 스케일링을 진행할 것 입니다.

물론 수평적 스케일링을 진행하는 것도 가능합니다.

  • 예를들면 읽기 용량을 늘리는 방법 입니다.

하지만 읽기 전용 복제본을 추가하는데에는 제한이 있기 떄문에 한계가 명확합니다.

그러기 떄문에 이러한 상황에서는 NoSQL이 효과적입니다.

일단 기본적으로 설계 덕분에 NoSQL은 수평적인 확장성을 가지게 됩니다.

즉 더 많은 쓰기, 읽기 용량이 필요한 경우 더 많은 인스턴스를 추가함으로써 스케일링이 가능합니다.

하지만 그렇다고 NoSQL과 SQL중 뭐가 더 좋은건은 없습니다.

  • 상황에 따라 다르게 사용이 되기 떄문입니다.

이러한 과점에서 DynamoDB에 대해서 설명하겠습니다.

기본적으로 NoSQL이며, 여러 AZ에 걸쳐서 복제가 가능합니다.

또한 IAM또한 지원하기 떄문에 보안에 대한 문제도 없습니다.


DtnamoDB 기초

기본적으로 테이블로 구성이 되며 각 테이블은 기본 키를 가지고 있씁니다.

그러기 떄문에 기본적으로  기본 키르 설정해야 합니다.

각 테이블은 항목이라고 부르는 행을 무한대로 가지고 있으며, 각 항목에는 속성이 있습니다.

키 전략에는 두가지고 있습니다.

  1. 파티션 키

HASH 전략이라고도 부르며 일반적인 DB와 유사하게 항목마다 고유해야 합니다.

예를들면 사용자 정보에 대한 DB가 있다면

USer_ID가 파티션 키로 동작을 하게 되고, 이에 따라서 데이터가 형성이 됩니다.

  • 일반적인 MYSQL을 생각하면 됩니다.
  1. HASH + RANGE

이 두개의 항목에 대한 조합은 항목마다 반드시 고유해야 합니다.

  • 즉 이는 두가지 항목이 고유해야 한다는 의미입니다.

예를들어 Sort_key는 파티션 키에 종속되는 것을 말합니다.

이러한 키 구조를 가지고 있는 테이블은 두 조합에 대해서 고유해야 합니다.

예를들어 게임 유저에 대한 정보를 저장하는 테이블이 있따고 가정을 하겠습니다.

게임은 여러가지고 있고 게임 사용자에 대한 파티션 키는 고유합니다.

그러면 한 사용자는 고유한 파티션 키를 가지고 여러개의 게임을 이용할 수 있고 이러한 관계가

HASH + RANGE 조합이라고 합니다.

DynamoDB는 기본 셋팅이 존재하기 떄문에 해당 기능을 활용하면 손쉽게 만들 수도 있습니다.

하지만 배우는 단계이기 떄문에 옵션에 대해서 조금씩 알아보았습니다.

테이블 클래스

대부분은 범용 테이블 클래스인 standard를 사용합니다.

standare-IA는 오래 사용하지 않는 데이터거나, 읽기 및 쓰기 작업이 많이 이루어 지지 않을떄에 사용하며 이로인해서 비용 적으로 이점을 가지는 클래스 입니다.

용량 모드

온디맨드 모드와 프리 티어인 프로비저닝 모드가 있습니다.

말 그대로 온디맨드는 사용하는 만큼 비용으 지불하는 것이고, 프로비저닝 모드는 미리 용량을 할당하고 해당 용량내에서 사용하는 모드 입니다.

이외에도 오토스케일링 설정 및 읽기, 쓰기에 사용하는 용량을 할당 가능합니다.

DynamoDB는 NoSQL과 동일하게 작동합니다.

예를들어 파티션 키가 A,B인 데이터가 있습니다.

기본적으로 둘의 파티션 키는 달라야 합니다.
- 기본키랑 같은 개념으로 이해하면 됩니다.

이떄 A의 속성에는 age, name이 있고,

B의 속성에는 address만이 있습니다.

이런 형태로 데이터가 만들어 졌다면 보통의 RDS는 에러가 발생을 합니다
- 왜냐하면 서로 다른 속성을 가지고 있기 떄문입니다.

하지만 NoSQL은 모든것을 허용하기 떄문에 오류가 발생을 하지 않고

B같은 경우에는 age, name값이 그냥 null로 처리가 됩니다.

이떄 중요한 점은 HASH + RANGE 조합으로 사용할 떄에는 파티션 키가 고유하지 않아도 된다는 점 입니다.

이 조합은 HASH + RANGE을 합한값이 고유해야 하는 것이기 떄문에 같은 파티션 키를 가지고 있어도 sort_key가 다르다면 데이터가 생성이 됩니다.

🍊 DynamoDB 읽기/쓰기 용량 모드

테이블의 용량을 제어하는 법으로 사전에 읽기/쓰기 처리량을 지정해야 합니다.

기본적으로 두가지 모드가 있습니다.

프로비저닝 모드

기본 설정 모드로 사전에 용량을 계획하여 사용해야 합니다.

두가지 설정을 해주어야 하는데 RCU와 WCU입니다.

RCU는 읽기 처리량을 의미하고, WCU는 쓰기 처리량을 의미합니다.

이러한 설정은 기본적으로 목표 사용량을 입력하면 자동으로 DynamoDB가 처리해 주며

만약 설정한 용량모드 더 많이 사용이 된다면 버스트 용량을 일시적으로 사용해주기 떄문에 무리가 없습니다.

만약 이러한 용량도 다 소진한다면 예외가 발생을 합니다.

  • 예외가 발생하면 작업을 다시 시도하는데 이를 지수 백오프 전략이라고 합니다.
WCU는 기본적으로 최대 1KB의 항목에 대해 초당 1개의 쓰기를 지원합니다.
- 즉 항목이 1KB이상이면 더 많은 WCU를 사용합니다.

예를들면 항목의 크기가 2KB이며, 초당 10개를 써야한다면

WCU는 20가 사용됩니다.

다른 예시로는 항목의 크기가 4.5KB이며 초당 6개의 항목을 써야 한다면

WCU는 총 30이 됩니다.
- 이떄 30이 되는 이유는 항상 올림이 되어서 계산이 되기 떄문에 4.5KB가 5KB로 계산이 됩니다.

다음에는 읽기에 대한 기본 개념 입니다.

일단 읽는 방법에는 2가지가 있습니다.

강력한 ,최종적 일관된 읽기모드가 있습니다.

DynamoDB가 서버리스 서비스 이지만 이면에는 서버가 있으며 이러한 서버를 통해서 관리가 됩니다.

서버가 3대가 있고 이러한 서버를 통해 관리 된다고 가정을 하겠습니다.

그러면 애플리케이션이 쓰기 요청을 보내면 DynamoDB에서는 해당 요청을 받아서 3대의 서버에 모두 복제를 할 것입니다.

그후 read요청을 하면 3대의 서버에서 데이터를 가져오게 될 것이고요

이떄 문제가 발생할 수 있습니다.

만약 쓰기 후에 데이터를 바로 읽어버린다면 복제 및 업데이트가 전반적으로 이루어 지지 않아서 오래된 데이터를 가져 올 수 있습니다.
- 이런 경우는 최정적 읽기 모드에서 발생합니다.
- 강력한 일관된 읽기모드에서는 발생하지 않습니다.

하지만 역시나 강력한 일관된 읽기 모드에서는 RCU를 두번 소비해야 하기 떄문에 더 비싼 쿼리가 될 것이고 지연시간 또한 발생을 할 것입니다.

다음에는 읽기 계산법 입니다.

기본적으로 4KB당 한개의 RCU가 사용이 됩니다.

하지만 일관된 읽기와 강력한 읽기는 계산법이 다릅니다.

예를들면 항목의 4KB이며, 강력한 읽기가 10개가 필요합니다.

그러면 필요한 RCU는 10RCU입니다.

항목의 크기가 12KB이며, 일관된 읽기가 16개가 필요합니다.

그러면 필요한 RCU는 (16 / 2) * (12 / 4) = 24RCU가 필요합니다.

**단순히 일관된 읽기 에서는 2를 나눠주면 됩니다.**

마찬가지로 RCU도 항목에 대한 값을 올림처리 하기 떄문에

만약 6KB에서 강력한 읽기가 10개가 필요하다면

필요한 RCU는 20개가 됩니다.

온디맨드 모드

워크로드에 기반하여 자동으로 스케일업/다운 합니다.

프로비저닝 할 필요가 없기 떄문에 관리가 필요 없지만 기본적으로 프로비저닝보다 비쌉니다.

  • RCU, WCU를 계산할 필요가 없습니다.

🍊 DynamoDB API 호출

PutItem

말 그대로 item을 새로 생성하는 API입니다.

UpdateItem

기존 항목을 수정하거나, 만약 기존 항목이 없다면 새 항목을 추가 합니다.

일부 속성만을 수정하는 것이 PutItem과의 차이점 입니다.

Conditional Writes

조건이 충족되면 쓰기, 업데이트, 삭제 만을 허용하며 하옴ㄱ에 관한 액세스를 지원하는 API입니다.

GetItem

데이터를 읽어오는 APi로 기본키에 기반합니다.

DeleteItem

데이터를 삭제하는 API입니다.

DeleteTable

테이블 자체를 삭제하는 API입니다.
테이블에 있는 모든 데이터를 삭제합니다.

Batch에 대해서 잠시 다루어 보겠습니다.

Batch는 데이터를 가져오거나, write할떄에 사용하는 항목으로 병렬처리를 하여 비용, 속도 면으로 빠른 서비스를 제공합니다.

대표적으로 BatchWriteItem, BatchGetItem이 있습니다.
- **중요한 점은 BatchUpdateItem이라는 API는 없습니다.**

🍊 DynamoDB Index

로컬 보조 인덱스(LSI)

LSI는 테이블에 대체 정렬 키를 제공합니다.

기본 테이블에 동일한 키를 가지지만 추가적으로 정렬 키를 얻는 것을 말합니다.
테이블 당 최대 5개의 LSI를 얻을 수 있습니다.

반드시 테이블 생성 시점에 정의 되어야 하며, 테이블 생성 후에는 생성이 불가능 합니다.

글로벌 보조 인덱스(GSI)

대체키를 제공하는 인덱스 입니다.
테이블 생성 후에도 추가나 생성이 가능합니다.


이 부분은 조금 이해가 되지 않기 떄문에 이론적으로만 좀 알아보고 후에 사용할떄 다시 공부하여 적용하는 방향으로 진행하겠습니다.

🍊 PartiQL

DynamoDB에서돋 SQL문을 사용하고 지원하는 서비스를 말합니다.

기본적으로 NoSQL이기 떄문에 SQL문이 없지만, SQL문에 익숙한 사람들을 위해서 존재하는 서비스 입니다.

그저 단순히 SQL문을 지원하는 것을 의미합니다.

🍊 낙관적 잠금

쉽게 말하면 특정 조건에 맞을떄만 API가 가능하게 하는 것을 말합니다.

예를들어 이와 같습니다.

파티션 키가 A이며 특성이 name, version이 있습니다.

해당 테이블은 version이 1일떄만 업데이트가 가능하다고 잠금을 걸어두면

오로지 version이라는 값이 1일떄에만 데이터 수정이 가능하고, 이후에는 수정이 불가능 합니다.

🍊 DAX = Accelerator

DAX는 DynamoDB를 위한 인 메모리 캐시 입니다.

이 서브시는 핫 키 문제를 해결 합니다.

특정 키, 항목을 너무 많이 읽으면 RCU에 스로틀링이 생겨나게 되지만 해당 서비스를 통해 캐시로 관리함으로써 이러한 문제를 방지합니다.

마찬가지로 TTL이 있으며 default값은 5분 입니다.

DAX를 사용할 떄에는 DAX 클러스트를 구성해야 하며, 이는 쉽게 말해 클러스트 모드로 노드를 돌리며 캐시 데이터를 가지고 있는 것과 같습니다.

만약 이러한 클러스트에서 애플리케이션의 요청에 맞는 값이 없다면 이떄 DynamoDB와 소통을 하게 됩니다.

최대 10개의 노드를 가질 수 있으며 최소 3개 이상을 설정해야 다중 AZ가 지원 됩니다.

  • 자주 사용되는 기술이며, 프리티어는 없습니다.

🚀 일래스틱 캐시와 차이점

혼용 해서 사용이 가능합니다.

일단 DAX는 기본적으로 개별 객체에 관한 캐시를 가지게 됩니다.

하지만 데이터 필터링등 추가적인 작업이 필요하면 계속해서 DAX에서 가져와서 필터링을 하는 것이 아니라, 필터링된 데이터를 일래스틱 캐시에 저장을 하고, 일래스틱 캐시에서 사용하는 것으로 조합할 수 있습니다.

이렇게 되면 다시 DAX에 들릴 필요 없이 일래스틱 캐시에서 값을 따오게 됩니다.

🍊 스트림 = Streams

스트림은 테이블에서 발생하는 모든 API요청에 대한 정렬된 목록입니다.

그러기 떄문에 수정 사항에 대한 정보를 스트림에서 확인 가능하며, 테이블의 전체 수정 사항 목록을 보여 주게 됩니다.

스트림 레코드는 여러 곳에 전송이 되는데 대표적으로 Kinesis에 보내져서 추가적인 작업을 할 수도 있습니다.

최대 보존 주기는 24시간이며, 더 오랜시간 보관하고 싶다면 Kinesis같은 곳에 보관해야 합니다.

🍊 DunamoDB TTL

해당 기능을 활용하면 타임스탬프 만료 이후에 자동으로 데이터를 삭제할 수 있습니다.

이는 wcu를 소비하지 않는 작업이기 떄문에 추가 비용이 생기지 않습니다.

하지만 해당 데이터는 즉시 바로 삭제가 되는 것이 아니라 48시간 이내에 복원이 가능하게 됩니다.

  • 이렇게 삭제 대기가 되어 있는 데이터 또한 애플리케이션의 에서 GetItem API를 요청하면 보이기 떄문에 추가적인 쿼리로 필터링을 해야 합니다.

🍊 CLI Option

--page-size

가장 자주 사용되는 옵션입니다.

데이터를 가져올 떄 사용이 되며 예시는 다읍과 같습니다.

API호출 한번으로 10,000개의 아이템을 검색하면 시간초과가 발생을 합니다.

하지만 --page-size를 100으로 지정하면 크기가 100인 API호출이 100회가 백그라운드에서 이루어지며 성공적으로 데이터를 가져 옵니다.

즉 더 많은 API호출이 가능하고, 시간 초과에 대한 문제도 방지가 가능합니다.

--max item

호출된 결과에 대해서 제한된 숫자의 값을 보여 줍니다.

주로 --starting-token과 결합하여 작동하며 예시는 다음과 같습니다.

예를들어 총 25개의 아이템이 있는 상황에서 --max item값을 5로 설정하면 5개만의 데이터만을 가져 옵니다.

이후 5개 이후에 index에 기반하여 5~10 index값을 가지고 싶다면 --starting-token값을 추가하여 사용 하면 됩니다.

🍊 세션 상태

기본적으로 DynamoDB는 데이터를 저장할 떄 사용이 됩니다.

세션 상태를 캐시로 저장할 떄 쓸 수도 있고 이러한 기능을 통해 로그인을 처리 할 수도 있습니다.


하지만 이러한 기능은 일래스틱 캐시에도 있습니다.

둘의 차이점에 대해서 이야기를 하자면 일래스틱 캐시는 전부 메모리에 위치합니다.

하지만 DynamoDB는 서버리스이며, 키 값 스토어 입니다.

만약 메모리에 위치해야 한다고 한다면 일래스틱 캐시가 정답일 것이고, 오토 스케일링 등을 이야기 한다면 DynamoDB가 정답일 것입니다.


이외에도 세션을 저장하는 또다른 방법은 디스크 입니다.

여러 EC2인스턴스에서 그 디스크를 공유하게 되는 이떄 EFS가 많이 사용됩니다.

해당 기능과 비교를 해보자면

EFS는 파일 시스템이고, DynamoDB는 DB입니다.

기본적으로 이런 차이가 있습니다.

하지만 EFS또한 스토리지로 사용을 할 수는 있습니다.

이떄 EFS는 로컬 캐싱에만 사용이 가능합니다..

  • 공유가 불가능 합니다.

마지막으로 S3와 비교를 해보게 습니다.

S3도 사용이 가능하지만 지연 시간이 높습니다.

그러기 떄문에 S3캐시는 좋은 선택지가 아닙니다.


즉 말을 정리하자면 결국 세션 및 캐시를 사용하고자 한다면 일래스틱 캐시 vs DynamoDB입니다.

선택은 메모리에 할지, 서버리스 또는 오토스케일링을 쓸지에 따라서 다르기 떄문에

설계 방향에 맞춰서 작업을 하면 됩니다.

🍊 S3와 결합 설계 예시

큰 객체를 업로드 하는 경우

DynamoDB는 테이블 마다 최대 400KB까지만 저장이 가능합니다.

그러기 떄문에 이미지나, 영상을 DynamoDB에 보관을 하는 것을 좋은 방법이 아닙니다.

이러한 큰 파일은 S3가 유리하며 그러기 떄문에 S3와 혼용하여 큰 데이터를 저장을 합니다.

S3에 데이터를 저장하고, 저장한 객체 키 값을 이제 DynamoDB에 저장을 함으로써 포인터 역할을 수행하게 구성하면 됩니다.

profile
Block_Chain 개발자 입니다. 해당 블로그는 네트워크에 관한 내용을 다루고 있습니다.

0개의 댓글