본문 바로가기

DataBase/DynamoDB

AWS DynamoDB 소개

AWS DynamoDB(NoSQL PaaS, Key/Value Store)

정확한 그림은 아니라지만, 뭐 대충 요런 포지션이 DynamoDB

NoSQL의 사용 이유(RDBMS 한계?)

Row->Document 성 데이터 이동

Scale-up의 한계 -> Scale-out 가능

비정형 데이터의 최적화

 

DynamoDB는 Partition과 Sort Key(옵션)만을 지원한다.

Sort Key를 생성하고 DynamoDB SDK의 get_item() API를 사용할 경우 Partition + Sort Key 조합만 지원한다.

 

만약 Sort Key를 생성했음에도 Partition Key만을 사용할 경우에는 필터를 걸거나, query() API를 사용해야 한다.

 

자유롭게 CRUD API를 구성하려면 GET, PUT Item 등의 API 보단 Query API 사용을 권장한다.

(필터의 경우 전체 데이터를 받은 후에 사용되기 때문)

get_item vs query

 

기존 테이블의 Partition , Sort Key만으로는 다양한 쿼리의 제약이 있을 수 있기 때문에 DynamoDB는 추가로 두 가지의 인덱스를 지원한다.

 

이것을 Local Secondary Index(LSI), Global Secondary Index(GSI) 라고 부른다.

 

LSI는 테이블 생성 시에만 만들 수 있으며, Partition Key는 기존 테이블의 키와 같게 지정해야 한다. 

또한 인덱스 크기의 경우 10GB 제약이 존재한다. 

같은 Partition Key에 대해 Sort Key가 추가로 필요할 경우 테이블 생성 시에 추가로 LSI를 지정할 수 있다.

 

GSI는 기존 테이블의 Partition Key와 별개의 Partition Key를 만들 수 있기 때문에 물리적으로 새로운 파티션에 저장된다. 

 

따라서 인덱스 크기 제한은 없으며, Read/Write Capacity를 별개로 지정할 수 있다. 그러나 Async 방식으로 동작하기 때문에 데이터의 무결성에 문제가 발생될 수 있다.

 

두 인덱스 모두 최대 5개까지 지정 가능하다.

 

Item 검색을 위해서는 Partition + Sort Key만 사용할 수 있다. 이 외 Attribute는 조건문의 값으로 사용할 수 없다. 딱 필요한 Key만을 사용하여 Item들을 검색할 수 있다.

 

가수(Partition), 노래(sort), 앨범, 발매 시기와 같은 Item이 있다면 가수&노래 혹은 가수만으로만 해당 Item을 검색할 수 있다.

 

만약 앨범을 통한 검색 기능도 필요하다면 GSI를 이용하여 앨범을 Partition Key로 등록하고 쿼리 결과를 원하는 Attribute를 추가할 수 있다.

 

그러나 GSI 비용이 증가되기 때문에 쿼리량이 많지 않다면, 기본 Partition Key로 스캔하고 필터를 이용하는 게 나을 수도 있다. 

 

또한 발매 시기 별로 가수의 노래를 검색하고 싶다면, 테이블 생성 시에 발매 시기를 Sort Key로 하는 LSI를 만들 수도 있다.

 

아무튼 기존 RDBMS 모델링 방식과 다르게, API Response 기준으로 DynamoDB를 모델링 해야한다. 제약이 많다. 복잡한 모델링이 필요한 DB에는 어울리지 않는다. 

기존 DBA도 DynamoDB를 위한 데이터 모델링을 따로 연구(?)해야 할 것이다. 어렵다... 나만 어렵나?

 

 

그런데 왜 DynamoDB를 쓸까?

그러나 이런 단점에도 불구하고, DynamoDB의 경우 거의 모든 것을 관리해주기 때문에 매우 매력적인 서비스다. 스토리지 자동 확장, IOPS 관리 등 (Aurora도 스토리지 자동 확장은 지원하나, IOPS 병목 문제는 따로 관리해야 한다.) 

 

아래 포스팅은 Cassandra -> DynamoDB 이관을 경험한 엔지니어(?)의 경험이 담겨있는 DynamoDB 관련 글이 시리즈로 연재되어 있다. 강추...

 

Sasidhar Sekar – Medium

Read writing from Sasidhar Sekar on Medium. Every day, Sasidhar Sekar and thousands of other voices read, write, and share important stories on Medium.

medium.com

 

 

API Gateway + Lambda + Dynamodb 조합이 꿀

Stateless 한 DynamoDB는 Lambda와 궁합이 잘 맞는다. 실제 패킷을 보면 443 Port(AWS API)로 동작하며, Say Hello 하고 Bye 한다.

DynamoDB

반면 MongoDB의 경우 mongo mongo 하고 Connection을 물고 있는 것을 알 수 있음. 일반적으로 사용하는 mongoose connection의 경우.

MongoDB

참고: https://www.youtube.com/watch?v=RfOt2bo0bSA(40분 영상인데 더 보강된 발표가 계속 나오므로 최근의 영상부터 시청 권장)

 

글로벌 보조 인덱스 - Amazon DynamoDB

글로벌 보조 인덱스 일부 애플리케이션은 서로 다른 속성을 쿼리 기준으로 사용하여 다양한 유형의 쿼리를 수행해야 할 수 있습니다. 이러한 요구 사항을 지원하기 위해 하나 이상의 글로벌 보조 인덱스를 생성하고 Amazon DynamoDB에서 이 인덱스에 대해 Query 요청을 발급할 수 있습니다. 시나리오: 글로벌 보조 인덱스 사용 모바일 게임 애플리케이션에서 사용자와 점수를 추적하는 GameScores라는 테이블을 예로 들어 설명해 보겠습니다. GameSc

docs.aws.amazon.com

 

Class: AWS.DynamoDB — AWS SDK for JavaScript

Class: AWS.DynamoDB Inherits: AWS.Service Object AWS.Service AWS.DynamoDB show all Identifier: dynamodb API Version: 2012-08-10 Defined in: (unknown) Overview Constructs a service interface object. Each API operation is exposed as a function on service. Se

docs.aws.amazon.com

DynamoDB의 API scan 등을 사용하면 "L", "M", "S" 등 각 Value의 Type까지 가져온다. json을 파싱할 때 거슬린다. 아래와 같이 하위 API를 wrapping 한 모듈을 사용하면 편리하다.

node.js의 경우 const dynamodb = new aws.DynamoDB.DocumentClient();

Python의 경우 boto3.resource('dynamodb')

 

DynamoDB — Boto 3 Docs 1.10.16 documentation

DynamoDB By following this guide, you will learn how to use the DynamoDB.ServiceResource and DynamoDB.Table resources in order to create tables, write items to tables, modify existing items, retrieve items, and query/filter the items in the table. Creating

boto3.amazonaws.com

boto3.client vs boto3.resource

 

boto3.resource와 boto3.client의 차이

boto3는 워낙 기능이 방대하다 보니 대부분의 경우에는 gist 등에서 예제를 찾아보게 되는데, boto3.resource 를 사용하는 예제도 있고, boto3.client 를 사용하는 예제도 있었다. 둘을 비교해 보자. Client low-l..

planbs.tistory.com

지원하는 data type은 아래와 같다. date와 같은 type은 없으나, String을 통해 date type과 같이 사용 가능하다. 또한 float type도 없다. Decimal을 통해 json 데이터 변환 후 저장을 해야 한다.

 

지원되는 데이터 형식 - Amazon DynamoDB

지원되는 데이터 형식 이 단원에서는 Amazon DynamoDB의 지원되는 기본 Java 데이터 형식, 컬렉션 및 임의의 데이터 형식을 설명합니다. Amazon DynamoDB는 다음과 같은 기본 Java 데이터 형식 및 기본 래퍼 클래스를 지원합니다. String Boolean, boolean Byte, byte Date(ISO_8601 밀리초 정밀도 문자열에 따라 UTC로 전환) Calendar(ISO_8601 밀리초 정밀도 문자열에 따라 UTC로 전

docs.aws.amazon.com

 

Convert Float to Decimal Data Types for Boto3 DynamoDB Using Python - Ruan Bekker's Blog

A quick post on a workaround when you need to convert float to decimal types. One thing I really don’t like about the AWS SDK for Python, specifically aimed towards DynamoDB is that Float types are not supported and that you should use Decimal types instea

blog.ruanbekker.com

 

 

DynamoDB 패키지는 없을까?

여기까지는 일단 패키지 없이 사용한 내용이고, DynamoDB도 dynamoose라는 ORM 관련 패키지가 있다. 직관적인 예제 등으로 설명이 잘 되어 있다.

 

dynamoose

Dynamoose is a modeling tool for Amazon's DynamoDB (inspired by Mongoose)

www.npmjs.com

사용법은 기존 mongoose와 비슷하나, connect가 따로 없기 때문에 mongoose connect 부분에서 Dynamoose의 createDynamooseInstance(); 를 이용해야 한다. 또한 population과 같은 다양한 기능도 지원 한다.

 

 

DynamoDB 쿼리 제약은?

추가로 GET Item은 1MB의 제약이 있어, scan과 같은 명령어 사용 시에는 LastEvaluatedKey 값을 체크한 후 재귀방식으로 실행이 필요하다. 

 

DynamoDB에서 스캔 작업 - Amazon DynamoDB

DynamoDB에서 스캔 작업 Amazon DynamoDB의 Scan 작업은 테이블 또는 보조 인덱스의 모든 항목을 읽어옵니다. 기본적으로 Scan 작업은 테이블이나 인덱스에 속한 항목의 데이터 속성을 모두 반환합니다. 하지만 Scan 작업에서 ProjectionExpression 파라미터를 사용하면 모두가 아닌 일부 속성만 가져올 수 있습니다. Scan은 항상 결과 집합을 반환합니다. 일치하는 항목이 없다면 결과 집합은 비어 있습니다. 단일 Scan 요

docs.aws.amazon.com

 

 

DynamoDB는 IOPS 컨트롤은?

DynamoDB의 Storage는 Aurora와 같이 자동 확장 해준다. 또한 아래 그림과 같이 기준 IO를 설정하고 임계치에 대해 AutoScaling 기능을 사용할 수 있다.

DynamoDB Read/Write capacity

추가로 On-demand라는 기능도 제공한다. 사용자는 IO에 대해 전혀 신경쓸 필요가 없어 진다. 물론 몇몇 인덱스에 IO가 몰리면 hot spot에 따른 스키마 변경이 필요할 수도 있긴 하다. 인덱스 키를 해쉬로 골고루 분산되게 적용했으면 회피할 수 있다. 

 

Amazon DynamoDB On-Demand 기능 출시 (서울 리전 포함) | Amazon Web Services

Amazon DynamoDB는 Amazon이 2007년에 발행한 Dynamo 백서에 실린 원칙을 바탕으로 만들어졌으며, 지난 몇 년 동안 AWS 고객의 데이터베이스 사용 방식을 더욱 단순화하는 새로운 기능이 많이 도입되었습니다. 유휴 상태의 암호화, 시점 복구, 인 메모리 캐싱, 오토 스케일링, 99.99%의 가동 시간 SLA(서비스 수준 계약) 등의 기능을 갖추었고, 멀티 리전 글로벌 테이블을 만들 수 있습니다. 하지만, 여전히 많은 […]

aws.amazon.com

 

실제 사용하면서 계속 내용을 덧붙여서 두서가 없다. 추가할 내용이 있으면 계속 업데이트 하겠음.

 

DynamoDB는 저렴한 서비스일까?

이건 데이터 모델링에 따라 API 설계에 따라 매우매우 달라질 수 있다.

 

우선 절대적인 DynamoDB의 가격은 저렴하지 않다. 

먼저 스토리지를 예로 들면 $0.27/1GB 다.

(S3의 경우 $0.025/1GB, RDS Aurora의 경우 $0.12/1GB)

따라서 스토리지 비용은 S3 대비 약 10배, RDS 기준으로는 약 2배 비싸다.

 

또한 여기에 Item 별로 100Byte가 추가된다. 가령 Item이 10,000,000개라면 1GB 스토리지 비용이 추가된다. 용량이 작은 Item들이 늘어나다 보면 절대 무시하지 못할 금액이다.

 

따라서 스토리지의 경우 TTL을 이용한 데이터 삭제 작업은 필수다. 사용하지 않는 데이터는 S3로 옮기자.

 

그리고 Read/Write API 비용이 추가된다.

 

Read의 경우 4KB 기준으로 1Unit이 필요하고, Write의 경우 1KB 기준으로 1Unit이 필요하다. Item들의 미세한 크기 차이에 따라 비용이 2배가 될 수도 있다.

 

또한 일관된 요청이나 트랜잭션 처리를 할 경우 2배의 Unit이 필요하다.

 

데이터 모델링에 따라 가격이 정말 최소 2배.. 최대는 정말 어마어마 하게 비용 차이가 날 것으로 생각된다.

따라서 DynamoDB를 주력으로 사용한다면 최우선 고려 사항은 비용에 따른 데이터 설계라고 생각한다.

 

내 생각에 DynamoDB의 뉴비와 고수는 "얼마나 비용 절감을 할 수 있는지" 같다. 확장성이야 단순하게 생각하면 칼럼만 추가하거나 인덱스(비용 증가)를 추가하면 되기에... 

 

IOPS Provisioning vs On-demand 중에 뭘 써야 할까?

Provisioning vs On-demand 비용을 비교하면, Provisioning의 경우 Write/Read Capacity를 기준으로 비용 발생

 

Amazon DynamoDB의 프로비저닝 용량 요금

프로비저닝된 용량 프로비저닝된 용량 모드를 선택한 경우 애플리케이션에서 필요할 것으로 예상하는 읽기 및 쓰기 용량을 지정합니다. Auto Scaling을 사용하여 지정된 사용률을 기준으로 테이블의 용량을 자동으로 조정하여 비용을 절감하면서 애플리케이션 성능을 보장할 수 있습니다. DynamoDB는 초당 1회의 쓰기(최대 1KB)에 1개의 WCU, 초당 1회의 트랜잭션 쓰기에 대해 2개의 WCU 요금을 청구합니다. 읽기의 경우 DynamoDB는 초당 1회의

aws.amazon.com

On-demand의 경우 DynamoDB 요청 수를 기준으로 비용 발생

 

Amazon DynamoDB의 온디맨드 용량 요금

DynamoDB 테이블에 대해 온디맨드 용량 모드를 선택한 경우 애플리케이션이 수행하는 읽기 및 쓰기에 대해 요금이 청구됩니다. 테이블의 처리량 용량을 관리할 필요 없이 API를 호출할 수 있습니다. DynamoDB는 하드웨어 리소스 관리를 처리하여 지연 시간이 짧고 일관된 성능으로 워크로드를 지원합니다. DynamoDB는 각 쓰기(최대 1KB)에 대해 1개의 쓰기 요청 유닛, 트랜잭션 쓰기에 대해 2개의 쓰기 요청 유닛 요금을 청구합니다. 읽기의 경우

aws.amazon.com

일반적으로 최적화 된 Provisioning이라면 가격이 더 저렴할 것으로 보이지만, 최초 On-demand를 사용하고 요청 수를 계산하여 Provisioning과 On-demand 비용 비교가 필요하다.

 

또한 아래와 같이 DynamoDB는 Global Table이라는 기능을 지원한다. 무엇인고 하면, 원하는 리전을 추가하면 각 리전의 DynamoDB의 Table끼리 데이터 동기화가 된다. 개꿀.

 

Write/Read 에 대한 모든 데이터가 동기화 된다. 그러나 Table Item들이 이미 있으면 생성이 불가능하므로, 최초에 생성해야 한다.

 

 

DynamoDB로 글로벌 서비스할 때는?

글로벌 서비스 시에 매우매우매우 유용하다. 각 리전별 App 서버에서 Endpoint만 변경해주면 된다. 

Dynaodb Global table

경험치를 키우기 위해 아래 토이 프로젝트의 DB를 DynamoDB로 사용해봤다.

(글로벌 노드를 두고 URL에 대한 Latency와 Header 값을 체크해주는 서비스)

 

Home | URL CHECKER

You have 9967 Coin (1 Coin === 1 Month) ❌

www.url-checker.com

스키마 변경과 성능 이슈에서 자유로워진다는 것이 가장 큰 장점이다. 또한 글로벌 배포 또한 쉽게 가능하다.

 

단점은 Hash, Range Key 만을 사용하기 때문에 복잡한 모델링의 데이터는 사용하기 힘들다.

웹페이지 게시판 같은 용도에 사용할 때 페이징 처리는 RDB와 같이 쉽게 할 수 없다. 

 

로그 등 단순하고 대규모 Row 데이터 적재가 고민이라면 고려할만하다. (물론 TTL로 데이터 정리는 필수)

응, 아니야 몽고디비 쓸거야

 

아래는 DynamoDB용 Client Tool

 

Amazon DynamoDB용 NoSQL Workbench – 미리보기 출시 | Amazon Web Services

Amazon DynamoDB는 아주 작은 데이터 요청 부터 초당 수백만 건의 요청으로 손쉽게 확장할 수 있는 문서 데이터베이스와 완전 관리형 키-값 NoSQL 데이터베이스입니다. DynamoDB 팀은 최근 네이티브 ACID

aws.amazon.com