Hello, DynamoDB

현재 맡게된 서비스의 DAU는 120 만명이다.
기념일에 맞추어 이벤트를 열면 트래픽이 급증한다고 한다.
회사의 개발팀은 프론트 5명, 백엔드 5명 이렇게 총 10명이며,
나를 포함 백엔드 5명이서 인프라, DB, 비즈니스 로직 구현을 전부 해야한다.
본래는 PostgreSQL 관계형 DB를 사용하고 있었지만,
더 유연한 트래픽 대응이 필요하다는 판단하에 DynamoDB 로의 마이그레이션을 진행한다고 한다.
그래서 우선적으로 DynamoDB 에 관련된 내용을 공부하며 지식을 정리해보기로 했다.
한가지 미리 받은 꿀팁은 DAX(DynamoDB Accerlerator) 는 기능이 매우 불안하므로, 굳이 욕심내지 말라는 의견을 받게 되었다.
DAX 를 읽다보니 인텔이 포기한 옵테인 영속 메모리와, 삼성이 이어받은 CXL 메모리가 생각났다.
스토리지 영역에 캐싱가능한 메모리 영역을 만들고, 결과적으로 스토리지의 속도를 DDR4 정도로 끌어올리는 기능이었는데
스토리지와 메모리 컨트롤러 구현이 어려워서 실제 성능과 안정성이 끔찍했던 기억이 났다.
학부 졸업 작품을 위해 울며겨자먹기로 해당 분야 연구실 생활을 했었는데, 아직까지도 제대로 적용되지 못한 것 같다.
DynamoDB 첫인상
테이블을 나누는 RDB 대신 DynamoDB 를 선택해야하는 이유로, RDB 와 정규화는 스토리지 용량을 절약하는데 특화되어있지만, 스토리지에 대한 비용이 싸진 지금은 스케일링과 확장을 위해 DynamoDB 를 선택해야한다는 블로그 글이 많았다.
DynamoDB 가 스케일링과 확장성이 좋다는 의견에는 동의한다. 특히 자동화된 파티셔닝과 S3 로 cold data 를 이전시켜버리는 기능은 이전 회사에서 직접 삽질했던 내용을 솔루션으로 제공하는 듯하여 무척 좋다고 생각했다.
그러나 RDB 의 핵심은 스토리지 용량의 절약이 아니다. RDB 의 핵심은 Relational Algebra 이론을 기반으로 스토리지 위에 데이터를 관리할 수 있도록 해주는 것이고, Algebra 의 핵심은 연산(operation) 의 성질을 보장할 수 있도록 하는데 있다.
가령 내가 다루고 있는 데이터 그룹과 하려고 하는 연산이 아벨리안 그룹의 성질을 만족한다고 하면, 교환법칙과 결합법칙이 성립하기에 나는 연산의 순서를 고려하지 않고 자유롭게 로직을 쪼개고 순서를 고려치 않고 체이닝하는 리팩토링을 할 수 있다.
개발을 하다보면 나오는 멱등성(Idempotency) 또한 Algebra 를 통해 증명할 수 있는 연산의 성질 중 하나이다.
Relational Algebra 이론에 기반을 둔다는 것은, Relational Algebra 가 보장해야한다고 명시한 연산의 여러 성질들을 믿고 사용할 수 있다는 것이다.
그리고 이러한 스펙을 Storage 로 제대로 구현했다면, 스펙 중 하나로 DB 프로그램은 ACID 트랜잭션을 지원하게 된다.
따라서 나는 RDB 의 가장 큰 장점은 효율적인 스토리지 절약이 아니라, 데이터 정합성의 보장과 어노말리 방지라고 생각한다.
DynamoDB 를 공부하면서 RDB 와 비교하며 다음 내용을 주의해보려 한다.
DynamoDB 가 보장하려고 하는 연산의 성질에는 어떤 것이 있는가?
DynamoDB 가 사용하는 Successor Ordinal 로직이 RDB 와 다른가?
그로 인해 식별자 설계를 RDB 와 다르게 할 필요성이 있는가?
Successor Ordinal 이 달라서 Cardinality 계산을 다르게 할 필요가 있는가?사용하는 자료구조의 성질이 다른가?
Sort Key 의 존재 때문에 OKVS(Ordered Key Value Store) 라는 표현이 나오는데,
B-Tree 혹은 Hash Table 과 어떻게 다른가?
DynamoDB 특징
서버리스로 구동되어서, 스케일링이 유연하다.
Key-Value Document NoSQL 이다.
멀티 리전 복제 기능을 지원한다.
Replica 에 대해 Eventually Consistent 와 Strongly Consistent 모드가 있다.
Strongly Consistent 에 Lock 이 사용되지 않기 때문에 비싸기만 하고 정합성 이슈가 똑같이 발생할 수 있다.
백업 및 복구에는 On-Demand 방식과 PITR(Point in Time Recovery) 2가지 방식이 있다.
ACID 트랜잭션을 지원한다. (MongoDB 는 가용성을 위해 ACID 가 아닌 BASE 트랜잭션이었는데, 차이가 있을지 궁금하다.)
Streams 기반 Change Data Capture 기능을 제공한다.
내부적으로 자동화된 파티셔닝을 지원한다.
Item 단위로 TTL 을 부과해서, 시간이 지나면 S3 로 이동시켜 cold data 로 만들어 비용절약을 할 수 있다.
DynamoDB 중요 개념들
Three components of DynamoDB Tables
Table : a collection of data
Attribute : a fundamental data element
Item : a group of attributes that is uniquely identifiable
Capacity mode
On-Demand : 요청 당 비용 발생
Provisioned : 초당 읽기 및 쓰기 성능으로 비용 부과
RCU: Read Capacity Unit
WCU: Write Capacity Unit
DynamoDB 의 인덱스 키
Primary Key
Partition Key : attribute 1개 짜리 key
Sort Key : 정렬을 하는데 사용하는 인덱스
Parition Key 로 식별하고, Sort Key 로 정렬한다.
Composite Primary Key = Partition Key + Sort Key
Secondary Index
LSI (Local secondary index)
테이블 생성 시 같이 생성되어야 함
테이블과 동일한 partition key 를 가지지만, sort key 를 다르게 할 수 있음
GSI (Global secondary index)
unique 할 필요조차 없는 인덱스
한 테이블 당 20개씩 만들 수 있음
Dynamo DB 사용시 주의점
NoSQL 이기에 클러스터링 인덱스 개념이 없다.
심지어 index 가 없는 테이블도 생성이 가능하다.
clustered index 가 없기에, PK 식별자를 정의했다고 인덱스가 존재한다고 취급하지 않는다.
빠른 식별을 위해서는 어떤 형식으로든 트리 자료구조가 필요할 텐데,
트리가 없이 철저하게 Hash 자료구조로 데이터를 접근하기 때문에 인덱스가 없다고 하는 것 같다.
그렇기 때문에 Key-Value NoSQL 이라고 Dynamo DB 를 하는 것 같다.
클러스터링 인덱스가 없어서 주의할 점
PK 가 선언되었다고, PK 속성으로 range 를 잡거나, 검색을 하는게 불가능하다.
Partition Key 는 hash 를 통한 Key-Value 방식이기 때문에 단 1개의 item 에 대해선 RUD 가 가능하다.
Partition Key 에 해당하는 attribute 를 조건으로 여러개의 item 에 대한 쿼리를 날리고 싶다면 별도의 Index 를 걸어야 한다.
Partition Key 만 존재하고 별도 인덱스가 없다면 DynamoDB 의 테이블에는 index 가 전혀 걸려있지 않다고 봐야 한다.
지원되는 CRUD
Put Item, Update Item, Batch Write Item, Delete Item
Get Item. Batch Get Item, Query, Scan
Reference
Subscribe to my newsletter
Read articles from 고정완 directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

고정완
고정완
I started my career as a IoT engineer for smart city solution. Then, I joined to a start-up company "Dreamfora" as one of starting member. I created an goal planning app for self-improvment. Now I am working at "MonyMony", making a couple diary application.