DynamoDB là gì?
Amazon DynamoDB là dịch vụ cơ sở dữ liệu NoSQL được quản lý hoàn toàn (fully managed) bởi AWS, hỗ trợ mô hình dữ liệu key-value và document. DynamoDB cung cấp hiệu năng ổn định ở mức mili-giây đơn (single-digit millisecond) bất kể quy mô dữ liệu, với khả năng tự động mở rộng (auto scaling) để xử lý hàng triệu request mỗi giây.
Use Cases phổ biến
- Gaming: Leaderboard, player sessions, game state — yêu cầu latency cực thấp
- E-commerce: Shopping cart, product catalog, order history
- IoT: Lưu trữ dữ liệu sensor, telemetry data với throughput cao
- Social Media: User profiles, feeds, likes, comments
- Ad Tech: Real-time bidding, click tracking, impression counting
- Session Management: Lưu session state cho web/mobile applications
- Serverless Backend: Kết hợp API Gateway + Lambda + DynamoDB
So sánh DynamoDB vs RDS (Relational Database)
| Tiêu chí | DynamoDB (NoSQL) | RDS (SQL) |
|---|---|---|
| Mô hình dữ liệu | Key-value / Document (schema-less) | Relational (schema-based, tables, rows, columns) |
| Ngôn ngữ truy vấn | PartiQL, API-based (GetItem, Query, Scan) | SQL (SELECT, JOIN, GROUP BY...) |
| Scaling | Horizontal (tự động, gần như vô hạn) | Vertical (scale up instance) + Read Replicas |
| Hiệu năng | Single-digit ms ở mọi quy mô | Phụ thuộc vào query complexity & instance size |
| JOIN | Không hỗ trợ (denormalize data) | Hỗ trợ đầy đủ |
| Transactions | Có (giới hạn 100 items, 4MB) | Có (ACID đầy đủ) |
| Quản lý | Serverless, fully managed | Managed nhưng vẫn cần chọn instance type |
| Chi phí | Pay-per-request hoặc provisioned capacity | Pay-per-instance (chạy 24/7) |
| Phù hợp cho | High-scale, low-latency, known access patterns | Complex queries, ad-hoc reporting, relationships |
Kiến trúc DynamoDB
DynamoDB tổ chức dữ liệu theo mô hình Tables → Items → Attributes. Mỗi table yêu cầu một Primary Key duy nhất để định danh từng item.
Các thành phần chính
Table (Bảng)
Là đơn vị tổ chức dữ liệu cao nhất. Mỗi table chứa nhiều items và yêu cầu định nghĩa Primary Key khi tạo. Không giới hạn số lượng items trong table.
Item (Bản ghi)
Tương đương một "row" trong SQL. Mỗi item là một tập hợp các attributes. Kích thước tối đa của một item là 400 KB.
Attribute (Thuộc tính)
Tương đương "column" trong SQL, nhưng DynamoDB là schema-less — mỗi item có thể có các attributes khác nhau (trừ Primary Key bắt buộc). Hỗ trợ các kiểu dữ liệu: String, Number, Binary, Boolean, Null, List, Map, Set.
Primary Key — Chìa khóa chính
DynamoDB hỗ trợ 2 loại Primary Key:
- Chỉ có Partition Key (PK)
- PK phải unique cho mỗi item
- Ví dụ:
userId= "USER#001" - Phù hợp khi mỗi entity chỉ có 1 record
- Gồm Partition Key + Sort Key (SK)
- Tổ hợp PK+SK phải unique
- Ví dụ: PK=
USER#001, SK=ORDER#2024-001 - Phù hợp cho one-to-many relationships
Cách DynamoDB phân phối dữ liệu
DynamoDB sử dụng consistent hashing trên Partition Key để phân phối items vào các partition vật lý. Mỗi partition có giới hạn:
- 10 GB dung lượng lưu trữ
- 3,000 RCU (Read Capacity Units) hoặc 1,000 WCU (Write Capacity Units)
Khi vượt giới hạn, DynamoDB tự động split partition. Tuy nhiên, throughput không được chia đều nếu access pattern không đồng đều.
Capacity Modes — Chế độ dung lượng
DynamoDB cung cấp 2 chế độ tính phí và quản lý throughput: Provisioned và On-Demand. Bạn có thể chuyển đổi giữa 2 mode mỗi 24 giờ.
- Bạn chỉ định trước số RCU/WCU cần thiết
- Trả phí theo capacity đã provision (dù dùng hay không)
- Hỗ trợ Auto Scaling để tự điều chỉnh
- Có thể mua Reserved Capacity (giảm đến 77%)
- Phù hợp: traffic ổn định, dự đoán được
- Không cần chỉ định capacity trước
- Trả phí theo số request thực tế (pay-per-request)
- Tự động scale lên/xuống ngay lập tức
- Đắt hơn ~6.5x so với Provisioned (per request)
- Phù hợp: traffic không dự đoán, spiky workloads
RCU & WCU — Cách tính toán
Read Capacity Unit (RCU)
| Loại đọc | Công thức | Ví dụ (item 6 KB, 10 reads/s) |
|---|---|---|
| Strongly Consistent Read | 1 RCU = 1 read/s cho item ≤ 4 KBRCU = ⌈item_size / 4KB⌉ × reads/s |
⌈6/4⌉ × 10 = 2 × 10 = 20 RCU |
| Eventually Consistent Read | 1 RCU = 2 reads/s cho item ≤ 4 KBRCU = ⌈item_size / 4KB⌉ × reads/s / 2 |
⌈6/4⌉ × 10 / 2 = 2 × 5 = 10 RCU |
| Transactional Read | Tốn gấp 2x Strongly ConsistentRCU = ⌈item_size / 4KB⌉ × reads/s × 2 |
⌈6/4⌉ × 10 × 2 = 2 × 20 = 40 RCU |
Write Capacity Unit (WCU)
| Loại ghi | Công thức | Ví dụ (item 2.5 KB, 5 writes/s) |
|---|---|---|
| Standard Write | 1 WCU = 1 write/s cho item ≤ 1 KBWCU = ⌈item_size / 1KB⌉ × writes/s |
⌈2.5/1⌉ × 5 = 3 × 5 = 15 WCU |
| Transactional Write | Tốn gấp 2x Standard WriteWCU = ⌈item_size / 1KB⌉ × writes/s × 2 |
⌈2.5/1⌉ × 5 × 2 = 3 × 10 = 30 WCU |
Auto Scaling (Provisioned Mode)
Khi dùng Provisioned Mode, bạn nên bật Auto Scaling để DynamoDB tự điều chỉnh RCU/WCU dựa trên CloudWatch metrics:
- Target Utilization: Mức sử dụng mục tiêu (ví dụ: 70%)
- Minimum Capacity: Giá trị RCU/WCU tối thiểu
- Maximum Capacity: Giá trị RCU/WCU tối đa
Auto Scaling sử dụng Application Auto Scaling service và tạo CloudWatch alarms tự động. Lưu ý: scale up nhanh (vài phút) nhưng scale down chậm hơn (15 phút cooldown).
Secondary Indexes — Chỉ mục phụ
Secondary Indexes cho phép bạn truy vấn dữ liệu theo các attributes khác ngoài Primary Key. DynamoDB hỗ trợ 2 loại: Global Secondary Index (GSI) và Local Secondary Index (LSI).
| Đặc điểm | GSI (Global Secondary Index) | LSI (Local Secondary Index) |
|---|---|---|
| Partition Key | Khác với base table (bất kỳ attribute nào) | Giống base table |
| Sort Key | Tùy chọn, bất kỳ attribute nào | Bắt buộc, khác với base table SK |
| Thời điểm tạo | Bất kỳ lúc nào (sau khi tạo table) | Chỉ khi tạo table (không thể thêm sau) |
| Giới hạn số lượng | 20 GSI / table | 5 LSI / table |
| Consistency | Chỉ Eventually Consistent | Eventually hoặc Strongly Consistent |
| Capacity | Có RCU/WCU riêng (tách biệt base table) | Dùng chung RCU/WCU với base table |
| Size limit | Không giới hạn | 10 GB per partition key value |
Projections — Chọn attributes cho Index
Khi tạo index, bạn chọn attributes nào sẽ được "project" (copy) vào index:
KEYS_ONLY— Chỉ copy Primary Key của base table + index key. Tiết kiệm storage nhất.INCLUDE— Copy thêm một số attributes cụ thể mà bạn chỉ định.ALL— Copy toàn bộ attributes. Tốn storage nhất nhưng không cần fetch lại base table.
- Chỉ tạo GSI khi thực sự cần query pattern mới — mỗi GSI tốn thêm WCU khi write
- Dùng
KEYS_ONLYhoặcINCLUDEthay vìALLđể giảm chi phí storage - GSI throttling có thể ảnh hưởng base table — đảm bảo GSI có đủ WCU
- Cân nhắc dùng sparse index: chỉ items có attribute đó mới xuất hiện trong index
DynamoDB Streams — Change Data Capture
DynamoDB Streams ghi lại mọi thay đổi (insert, update, delete) trên table theo thứ tự thời gian. Dữ liệu stream được lưu giữ trong 24 giờ và có thể được xử lý bởi Lambda, Kinesis, hoặc ứng dụng tùy chỉnh.
Stream View Types
| View Type | Nội dung record | Use Case |
|---|---|---|
KEYS_ONLY |
Chỉ Primary Key của item bị thay đổi | Trigger nhẹ, chỉ cần biết item nào thay đổi |
NEW_IMAGE |
Toàn bộ item sau khi thay đổi | Sync data sang hệ thống khác |
OLD_IMAGE |
Toàn bộ item trước khi thay đổi | Audit log, rollback |
NEW_AND_OLD_IMAGES |
Cả trước và sau khi thay đổi | So sánh diff, complex event processing |
Lambda Trigger với DynamoDB Streams
Đây là pattern phổ biến nhất: Lambda function tự động được invoke khi có thay đổi trong table.
import json
def lambda_handler(event, context):
for record in event['Records']:
event_name = record['eventName'] # INSERT | MODIFY | REMOVE
if event_name == 'INSERT':
new_item = record['dynamodb']['NewImage']
print(f"New item created: {json.dumps(new_item)}")
# Gửi welcome email, sync to Elasticsearch, etc.
elif event_name == 'MODIFY':
old_item = record['dynamodb']['OldImage']
new_item = record['dynamodb']['NewImage']
print(f"Item updated from {old_item} to {new_item}")
elif event_name == 'REMOVE':
old_item = record['dynamodb']['OldImage']
print(f"Item deleted: {json.dumps(old_item)}")
return {'statusCode': 200}
- Stream records được lưu giữ 24 giờ rồi tự động xóa
- Mỗi table chỉ có 1 stream tại một thời điểm
- Lambda đọc stream theo batch (có thể cấu hình batch size)
- Đảm bảo Lambda function idempotent vì có thể nhận duplicate records
- Streams là nền tảng cho Global Tables replication
DAX — DynamoDB Accelerator
DAX (DynamoDB Accelerator) là dịch vụ in-memory cache được quản lý hoàn toàn, tương thích API với DynamoDB. DAX giảm độ trễ đọc từ mili-giây xuống micro-giây (microseconds) mà không cần thay đổi application logic.
Đặc điểm chính của DAX
| Đặc điểm | Chi tiết |
|---|---|
| Hiệu năng | Giảm latency từ ms → microseconds (đến 10x nhanh hơn) |
| Tương thích API | Chỉ cần đổi DynamoDB client → DAX client, không cần sửa code logic |
| Cluster | Tối thiểu 1 node, khuyến nghị 3+ nodes cho HA (multi-AZ) |
| Cache TTL | Item Cache: 5 phút (default), Query Cache: 5 phút (default) |
| Write-through | Writes đi qua DAX → DynamoDB, cache được cập nhật tự động |
| Encryption | Encryption at rest (KMS) và in-transit (TLS) |
| VPC | DAX cluster chạy trong VPC của bạn |
- Read-heavy workloads (nhiều GetItem, Query)
- Cần latency microsecond
- Dữ liệu đọc lặp lại nhiều (hot keys)
- Muốn giảm RCU cost trên DynamoDB
- Write-heavy workloads (DAX không cache writes hiệu quả)
- Cần Strongly Consistent reads (DAX chỉ hỗ trợ Eventually Consistent)
- Application không chạy trong VPC
- Ít read operations hoặc data ít lặp lại
Global Tables — Bảng toàn cầu
Global Tables cung cấp khả năng replication đa vùng (multi-region) với mô hình active-active. Bạn có thể đọc và ghi ở bất kỳ region nào, DynamoDB tự động đồng bộ dữ liệu giữa các replica tables.
Yêu cầu & Đặc điểm
- Table phải bật DynamoDB Streams (NEW_AND_OLD_IMAGES)
- Replication là asynchronous — thường dưới 1 giây
- Conflict resolution: Last Writer Wins (dựa trên timestamp)
- Mỗi replica table có thể dùng capacity mode riêng (Provisioned hoặc On-Demand)
- Hỗ trợ encryption at rest với KMS (CMK hoặc AWS-owned key)
- Có thể thêm/xóa region bất kỳ lúc nào (không downtime)
Backup & Recovery — Sao lưu & Phục hồi
DynamoDB cung cấp nhiều phương thức backup để bảo vệ dữ liệu, từ on-demand backup đến continuous backup với Point-in-Time Recovery.
So sánh các phương thức Backup
| Tính năng | On-Demand Backup | PITR | Export to S3 |
|---|---|---|---|
| Kích hoạt | Thủ công hoặc qua API/CLI | Bật 1 lần, tự động continuous | Thủ công hoặc scheduled |
| Retention | Vĩnh viễn (cho đến khi xóa) | 35 ngày gần nhất | Tùy S3 lifecycle policy |
| Restore | Restore sang table mới | Restore sang table mới (bất kỳ thời điểm) | Import lại từ S3 |
| Ảnh hưởng hiệu năng | Không | Không | Không (dùng PITR snapshot) |
| Cross-region | Có (copy backup sang region khác) | Không (chỉ trong cùng region) | Có (S3 cross-region) |
| Chi phí | $0.10/GB/tháng (backup storage) | $0.20/GB/tháng | $0.11/GB (export) + S3 storage |
Security — Bảo mật
DynamoDB cung cấp nhiều lớp bảo mật từ network level đến data level, tuân thủ các tiêu chuẩn compliance như SOC, PCI DSS, HIPAA, ISO.
IAM — Identity & Access Management
Mọi truy cập DynamoDB đều thông qua IAM. Bạn có thể kiểm soát chi tiết đến từng action và resource:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"dynamodb:GetItem",
"dynamodb:Query"
],
"Resource": "arn:aws:dynamodb:ap-southeast-1:123456789012:table/Users",
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": ["${www.amazon.com:user_id}"]
},
"StringEqualsIfExists": {
"dynamodb:Select": "SPECIFIC_ATTRIBUTES"
},
"ForAllValues:StringEquals": {
"dynamodb:Attributes": ["userId", "name", "email"]
}
}
}
]
}
Fine-Grained Access Control
DynamoDB hỗ trợ condition keys đặc biệt trong IAM policy:
dynamodb:LeadingKeys— Giới hạn truy cập theo Partition Key (user chỉ đọc data của mình)dynamodb:Attributes— Giới hạn attributes nào được đọc/ghidynamodb:Select— Kiểm soát projection (ALL_ATTRIBUTES, SPECIFIC_ATTRIBUTES...)
Encryption — Mã hóa
| Loại | Chi tiết |
|---|---|
| Encryption at Rest | Mặc định bật cho tất cả tables. 3 tùy chọn: AWS Owned Key (miễn phí), AWS Managed Key (aws/dynamodb), Customer Managed Key (CMK — bạn quản lý rotation) |
| Encryption in Transit | Mọi kết nối đến DynamoDB đều qua HTTPS/TLS. Không cần cấu hình thêm. |
VPC Endpoints
Sử dụng VPC Gateway Endpoint để truy cập DynamoDB từ VPC mà không cần đi qua internet. Traffic đi qua AWS private network, tăng bảo mật và giảm latency.
# Tạo VPC Gateway Endpoint cho DynamoDB aws ec2 create-vpc-endpoint \ --vpc-id vpc-0abc123def456 \ --service-name com.amazonaws.ap-southeast-1.dynamodb \ --route-table-ids rtb-0abc123def456 # Kiểm tra endpoint aws ec2 describe-vpc-endpoints \ --filters "Name=service-name,Values=com.amazonaws.ap-southeast-1.dynamodb"
- ✅ Sử dụng IAM roles thay vì access keys cho EC2/Lambda
- ✅ Bật CloudTrail để audit mọi API calls đến DynamoDB
- ✅ Dùng VPC Endpoint cho workloads trong VPC
- ✅ Áp dụng least privilege — chỉ cấp quyền cần thiết
- ✅ Dùng Customer Managed Key (CMK) cho dữ liệu nhạy cảm
- ✅ Bật deletion protection cho production tables
DynamoDB Transactions — Giao dịch ACID
DynamoDB Transactions cho phép thực hiện nhiều operations (đọc/ghi) trên nhiều items và tables trong một giao dịch ACID (Atomicity, Consistency, Isolation, Durability). Tất cả operations trong transaction hoặc thành công hết, hoặc thất bại hết.
Hai API chính
- Tối đa 100 actions trong 1 transaction
- Tổng kích thước ≤ 4 MB
- Hỗ trợ:
Put,Update,Delete,ConditionCheck - Idempotent với
ClientRequestToken - Chi phí: 2x WCU so với standard write
- Tối đa 100 actions trong 1 transaction
- Tổng kích thước ≤ 4 MB
- Hỗ trợ:
Get(read multiple items atomically) - Đảm bảo snapshot isolation
- Chi phí: 2x RCU so với standard read
Ví dụ: Chuyển tiền giữa 2 tài khoản
import boto3
dynamodb = boto3.client('dynamodb')
def transfer_money(from_account, to_account, amount):
"""Chuyển tiền atomic: trừ account A, cộng account B"""
try:
dynamodb.transact_write_items(
TransactItems=[
{
'Update': {
'TableName': 'Accounts',
'Key': {'accountId': {'S': from_account}},
'UpdateExpression': 'SET balance = balance - :amount',
'ConditionExpression': 'balance >= :amount',
'ExpressionAttributeValues': {
':amount': {'N': str(amount)}
}
}
},
{
'Update': {
'TableName': 'Accounts',
'Key': {'accountId': {'S': to_account}},
'UpdateExpression': 'SET balance = balance + :amount',
'ExpressionAttributeValues': {
':amount': {'N': str(amount)}
}
}
},
{
'Put': {
'TableName': 'Transactions',
'Item': {
'txId': {'S': 'TX-2024-001'},
'fromAccount': {'S': from_account},
'toAccount': {'S': to_account},
'amount': {'N': str(amount)},
'status': {'S': 'completed'}
}
}
}
]
)
print("Transfer successful!")
except dynamodb.exceptions.TransactionCanceledException as e:
print(f"Transfer failed: {e}")
# Không có partial update — tất cả rollback
- Tối đa 100 items per transaction (across tables)
- Tổng kích thước ≤ 4 MB
- Không thể target cùng 1 item nhiều lần trong 1 transaction
- Chi phí gấp 2x so với standard operations
- Transactions không hỗ trợ trên Global Tables cross-region
- Nếu bị conflict (item đang bị modify bởi transaction khác) →
TransactionConflictException
Các lỗi thường gặp
Dưới đây là các vấn đề phổ biến khi làm việc với DynamoDB và cách khắc phục.
1. Throttling — ProvisionedThroughputExceededException
- Vượt quá RCU/WCU đã provision
- Hot partition — một partition nhận quá nhiều traffic
- GSI không đủ WCU → throttle ngược base table
- Burst capacity đã hết
Cách khắc phục:
- Thiết kế Partition Key phân tán đều (high cardinality)
- Bật Auto Scaling hoặc chuyển sang On-Demand mode
- Sử dụng exponential backoff trong application code
- Kiểm tra và tăng WCU cho GSI
- Dùng DAX để giảm read load
2. Hot Partition
Xảy ra khi một số ít partition key values nhận phần lớn traffic. Ví dụ: dùng date làm PK → tất cả writes trong ngày đổ vào 1 partition.
3. Item Size Exceeded (400 KB limit)
Mỗi item tối đa 400 KB (bao gồm attribute names + values). Cách xử lý:
- Nén (compress) large attributes trước khi lưu
- Lưu large objects (images, files) trên S3, chỉ lưu S3 URL trong DynamoDB
- Tách item thành nhiều items nhỏ hơn (vertical partitioning)
4. Cost Surprises — Chi phí bất ngờ
- Scan operations: Scan đọc toàn bộ table → tốn rất nhiều RCU
- On-Demand mode: Đắt hơn 6.5x so với Provisioned nếu traffic ổn định
- GSI quá nhiều: Mỗi GSI tốn thêm WCU cho mỗi write vào base table
- Large items: RCU/WCU tính theo item size — items lớn tốn nhiều capacity hơn
- Global Tables: Replicated writes tốn thêm rWCU ở mỗi region
- Quên tắt PITR/Streams: Các tính năng phụ cũng có chi phí
5. Các lỗi API thường gặp
| Error | HTTP Code | Nguyên nhân & Cách xử lý |
|---|---|---|
ProvisionedThroughputExceededException |
400 | Vượt RCU/WCU → Exponential backoff, tăng capacity, hoặc chuyển On-Demand |
ConditionalCheckFailedException |
400 | Condition expression không thỏa mãn → Kiểm tra logic condition |
ValidationException |
400 | Request không hợp lệ (sai data type, thiếu key...) → Kiểm tra request format |
ResourceNotFoundException |
400 | Table/Index không tồn tại → Kiểm tra tên table và region |
ItemCollectionSizeLimitExceededException |
400 | Vượt 10 GB cho 1 partition key (khi có LSI) → Redesign data model |
InternalServerError |
500 | Lỗi phía AWS → Retry với exponential backoff |
Tips & Best Practices
Thiết kế DynamoDB đúng cách từ đầu sẽ giúp bạn tránh được nhiều vấn đề về hiệu năng và chi phí. Dưới đây là các best practices quan trọng nhất.
1. Single-Table Design
Single-Table Design là pattern phổ biến nhất trong DynamoDB: lưu nhiều entity types (Users, Orders, Products...) trong cùng 1 table, sử dụng composite primary key để phân biệt.
┌──────────────────┬─────────────────────┬──────────────────────────────┐
│ PK │ SK │ Attributes │
├──────────────────┼─────────────────────┼──────────────────────────────┤
│ USER#001 │ PROFILE │ name, email, phone │
│ USER#001 │ ORDER#2024-001 │ total, status, createdAt │
│ USER#001 │ ORDER#2024-002 │ total, status, createdAt │
│ USER#001 │ ADDRESS#home │ street, city, zipCode │
│ USER#002 │ PROFILE │ name, email, phone │
│ USER#002 │ ORDER#2024-003 │ total, status, createdAt │
│ PRODUCT#A100 │ METADATA │ name, price, category │
│ PRODUCT#A100 │ REVIEW#001 │ rating, comment, userId │
│ PRODUCT#A100 │ REVIEW#002 │ rating, comment, userId │
└──────────────────┴─────────────────────┴──────────────────────────────┘
Access Patterns:
→ Lấy profile user: Query PK="USER#001", SK="PROFILE"
→ Lấy tất cả orders: Query PK="USER#001", SK begins_with("ORDER#")
→ Lấy product + reviews: Query PK="PRODUCT#A100"
- Giảm số lượng API calls (1 Query lấy nhiều entity types)
- Giảm latency (không cần multiple round-trips)
- Transactions dễ dàng hơn (cùng table)
- Ít tables = ít quản lý capacity
- Phức tạp hơn khi thiết kế và maintain
- Khó hiểu cho team mới
- Cần biết trước tất cả access patterns
- Khó thay đổi access patterns sau này
2. Partition Key Design — Thiết kế khóa phân vùng
Partition Key tốt phải có high cardinality (nhiều giá trị unique) và uniform distribution (traffic phân bố đều).
| ❌ PK kém | ✅ PK tốt | Lý do |
|---|---|---|
status (active/inactive) |
userId |
status chỉ có 2 giá trị → hot partition |
date (2024-01-15) |
userId#date |
Tất cả writes trong ngày đổ vào 1 partition |
country (VN, US, JP) |
orderId |
Ít giá trị, traffic không đều giữa các nước |
deviceType (iOS/Android) |
deviceId |
Chỉ 2-3 giá trị → extreme hot partition |
Write Sharding — Kỹ thuật phân tán ghi
Khi PK tự nhiên có low cardinality, thêm random suffix hoặc calculated suffix để phân tán:
# Thay vì PK = "2024-01-15" (hot partition)
# Thêm random suffix: PK = "2024-01-15#3"
import random
def get_sharded_pk(date_str, num_shards=10):
"""Tạo sharded partition key"""
shard = random.randint(0, num_shards - 1)
return f"{date_str}#{shard}"
# Write: PK sẽ là "2024-01-15#0", "2024-01-15#1", ..., "2024-01-15#9"
# Read: Cần query tất cả 10 shards rồi merge kết quả
pk = get_sharded_pk("2024-01-15")
# Scatter-Gather pattern cho read
def query_all_shards(date_str, num_shards=10):
results = []
for shard in range(num_shards):
pk = f"{date_str}#{shard}"
items = dynamodb.query(
TableName='Events',
KeyConditionExpression='PK = :pk',
ExpressionAttributeValues={':pk': {'S': pk}}
)
results.extend(items['Items'])
return results
3. Cost Optimization — Tối ưu chi phí
4. Các Pattern quan trọng khác
- Optimistic Locking: Dùng
ConditionExpressionvới version number để tránh concurrent update conflicts - TTL (Time to Live): Set attribute chứa epoch timestamp → DynamoDB tự xóa item khi hết hạn (miễn phí, không tốn WCU)
- Sparse Index: Chỉ items có attribute được index mới xuất hiện trong GSI → tiết kiệm storage và RCU
- Adjacency List: Dùng PK + SK để model graph relationships (many-to-many)
- Composite Sort Key: Kết hợp nhiều attributes vào SK:
STATUS#SHIPPED#2024-01-15→ hỗ trợ begins_with queries
AWS CLI Cheat Sheet — DynamoDB
Tổng hợp các lệnh AWS CLI thường dùng nhất khi làm việc với DynamoDB.
Quản lý Table
# Tạo table với Composite Primary Key (Provisioned mode)
aws dynamodb create-table \
--table-name Users \
--attribute-definitions \
AttributeName=PK,AttributeType=S \
AttributeName=SK,AttributeType=S \
--key-schema \
AttributeName=PK,KeyType=HASH \
AttributeName=SK,KeyType=RANGE \
--billing-mode PROVISIONED \
--provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5
# Tạo table On-Demand mode
aws dynamodb create-table \
--table-name Events \
--attribute-definitions AttributeName=eventId,AttributeType=S \
--key-schema AttributeName=eventId,KeyType=HASH \
--billing-mode PAY_PER_REQUEST
# Liệt kê tables
aws dynamodb list-tables
# Xem thông tin table
aws dynamodb describe-table --table-name Users
# Xóa table
aws dynamodb delete-table --table-name Users
# Chuyển đổi capacity mode
aws dynamodb update-table \
--table-name Users \
--billing-mode PAY_PER_REQUEST
CRUD Operations
# PutItem — Tạo/ghi đè item
aws dynamodb put-item \
--table-name Users \
--item '{
"PK": {"S": "USER#001"},
"SK": {"S": "PROFILE"},
"name": {"S": "Nguyen Van Minh"},
"email": {"S": "minh@example.com"},
"age": {"N": "28"}
}'
# GetItem — Đọc 1 item (Strongly Consistent)
aws dynamodb get-item \
--table-name Users \
--key '{"PK": {"S": "USER#001"}, "SK": {"S": "PROFILE"}}' \
--consistent-read
# UpdateItem — Cập nhật attributes
aws dynamodb update-item \
--table-name Users \
--key '{"PK": {"S": "USER#001"}, "SK": {"S": "PROFILE"}}' \
--update-expression "SET age = :newAge, updatedAt = :now" \
--expression-attribute-values '{
":newAge": {"N": "29"},
":now": {"S": "2024-01-15T10:30:00Z"}
}'
# DeleteItem — Xóa item
aws dynamodb delete-item \
--table-name Users \
--key '{"PK": {"S": "USER#001"}, "SK": {"S": "PROFILE"}}'
# Conditional Write — Chỉ ghi nếu điều kiện thỏa mãn
aws dynamodb put-item \
--table-name Users \
--item '{"PK": {"S": "USER#003"}, "SK": {"S": "PROFILE"}, "name": {"S": "Test"}}' \
--condition-expression "attribute_not_exists(PK)"
Query & Scan
# Query — Lấy tất cả items của 1 user
aws dynamodb query \
--table-name Users \
--key-condition-expression "PK = :pk" \
--expression-attribute-values '{":pk": {"S": "USER#001"}}'
# Query — Lấy orders của user (SK begins_with)
aws dynamodb query \
--table-name Users \
--key-condition-expression "PK = :pk AND begins_with(SK, :sk)" \
--expression-attribute-values '{
":pk": {"S": "USER#001"},
":sk": {"S": "ORDER#"}
}'
# Query với filter (filter sau khi đọc, vẫn tốn RCU)
aws dynamodb query \
--table-name Users \
--key-condition-expression "PK = :pk AND begins_with(SK, :sk)" \
--filter-expression "total > :minTotal" \
--expression-attribute-values '{
":pk": {"S": "USER#001"},
":sk": {"S": "ORDER#"},
":minTotal": {"N": "100000"}
}'
# Query trên GSI
aws dynamodb query \
--table-name Users \
--index-name email-index \
--key-condition-expression "email = :email" \
--expression-attribute-values '{":email": {"S": "minh@example.com"}}'
# Scan — Đọc toàn bộ table (TRÁNH dùng trong production!)
aws dynamodb scan --table-name Users --max-items 10
# Scan với filter
aws dynamodb scan \
--table-name Users \
--filter-expression "age > :minAge" \
--expression-attribute-values '{":minAge": {"N": "25"}}'
Batch Operations
# BatchWriteItem — Ghi nhiều items (tối đa 25 items, 16 MB)
aws dynamodb batch-write-item --request-items '{
"Users": [
{
"PutRequest": {
"Item": {
"PK": {"S": "USER#010"},
"SK": {"S": "PROFILE"},
"name": {"S": "User 10"}
}
}
},
{
"DeleteRequest": {
"Key": {
"PK": {"S": "USER#005"},
"SK": {"S": "PROFILE"}
}
}
}
]
}'
# BatchGetItem — Đọc nhiều items (tối đa 100 items, 16 MB)
aws dynamodb batch-get-item --request-items '{
"Users": {
"Keys": [
{"PK": {"S": "USER#001"}, "SK": {"S": "PROFILE"}},
{"PK": {"S": "USER#002"}, "SK": {"S": "PROFILE"}}
],
"ProjectionExpression": "PK, #n, email",
"ExpressionAttributeNames": {"#n": "name"}
}
}'
Backup, Streams & TTL
# Bật Point-in-Time Recovery
aws dynamodb update-continuous-backups \
--table-name Users \
--point-in-time-recovery-specification PointInTimeRecoveryEnabled=true
# Tạo On-Demand Backup
aws dynamodb create-backup \
--table-name Users \
--backup-name users-backup-2024-01-15
# Bật DynamoDB Streams
aws dynamodb update-table \
--table-name Users \
--stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES
# Bật TTL
aws dynamodb update-time-to-live \
--table-name Sessions \
--time-to-live-specification Enabled=true,AttributeName=expiresAt
# Tạo GSI
aws dynamodb update-table \
--table-name Users \
--attribute-definitions AttributeName=email,AttributeType=S \
--global-secondary-index-updates '[
{
"Create": {
"IndexName": "email-index",
"KeySchema": [{"AttributeName": "email", "KeyType": "HASH"}],
"Projection": {"ProjectionType": "ALL"},
"ProvisionedThroughput": {
"ReadCapacityUnits": 5,
"WriteCapacityUnits": 5
}
}
}
]'
# Export table to S3
aws dynamodb export-table-to-point-in-time \
--table-arn arn:aws:dynamodb:ap-southeast-1:123456789012:table/Users \
--s3-bucket my-dynamodb-exports \
--s3-prefix users/ \
--export-format DYNAMODB_JSON
# SELECT (Query)
aws dynamodb execute-statement \
--statement "SELECT * FROM Users WHERE PK='USER#001' AND begins_with(SK, 'ORDER#')"
# INSERT
aws dynamodb execute-statement \
--statement "INSERT INTO Users VALUE {'PK': 'USER#099', 'SK': 'PROFILE', 'name': 'Test User'}"
# UPDATE
aws dynamodb execute-statement \
--statement "UPDATE Users SET age=30 WHERE PK='USER#001' AND SK='PROFILE'"
# DELETE
aws dynamodb execute-statement \
--statement "DELETE FROM Users WHERE PK='USER#099' AND SK='PROFILE'"