KoderKoder.ai
Bảng giáDoanh nghiệpGiáo dụcDành cho nhà đầu tư
Đăng nhậpBắt đầu

Sản phẩm

Bảng giáDoanh nghiệpDành cho nhà đầu tư

Tài nguyên

Liên hệHỗ trợGiáo dụcBlog

Pháp lý

Chính sách bảo mậtĐiều khoản sử dụngBảo mậtChính sách sử dụng chấp nhận đượcBáo cáo vi phạm

Mạng xã hội

LinkedInTwitter
Koder.ai
Ngôn ngữ

© 2026 Koder.ai. Bảo lưu mọi quyền.

Trang chủ›Blog›Amazon DynamoDB Giải Thích: Xây Dựng Hệ Thống Có Khả Năng Mở Rộng
30 thg 11, 2025·8 phút

Amazon DynamoDB Giải Thích: Xây Dựng Hệ Thống Có Khả Năng Mở Rộng

Tìm hiểu Amazon DynamoDB là gì, mô hình NoSQL hoạt động ra sao, và các mẫu thiết kế thực tiễn cho hệ thống mở rộng, lưu trữ độ trễ thấp và microservices.

Amazon DynamoDB Giải Thích: Xây Dựng Hệ Thống Có Khả Năng Mở Rộng

DynamoDB là gì và vì sao các đội chọn nó

Amazon DynamoDB là dịch vụ cơ sở dữ liệu NoSQL được quản lý hoàn toàn của AWS, thiết kế cho những ứng dụng cần thời gian đọc và ghi có độ trễ thấp ổn định ở gần như bất kỳ quy mô nào. “Quản lý hoàn toàn” nghĩa là AWS lo phần cơ sở hạ tầng—cấp phát phần cứng, nhân bản, vá lỗi và nhiều tác vụ vận hành khác—để các đội có thể tập trung vào phát triển tính năng thay vì quản lý máy chủ cơ sở dữ liệu.

Về cơ bản, DynamoDB lưu dữ liệu dưới dạng items (hàng) trong tables, nhưng mỗi item có thể có các thuộc tính linh hoạt. Mô hình dữ liệu dễ hiểu nhất khi coi nó là sự kết hợp của:

  • Key-value: lấy một item nhanh bằng khóa chính, giống như tra một bản ghi theo ID.
  • Document: lưu các thuộc tính lồng nhau (maps và lists), tương tự JSON, hữu ích cho các trường liên quan mà không cần schema cứng.

Các đội chọn DynamoDB khi muốn hiệu năng dự đoán và vận hành đơn giản cho những khối lượng công việc không phù hợp với phép nối quan hệ. Nó thường được dùng cho microservices (mỗi dịch vụ sở hữu dữ liệu của nó), ứng dụng serverless có lưu lượng đột ngột, và hệ thống hướng sự kiện phản ứng theo thay đổi dữ liệu.

Bài viết này đi qua các khối xây dựng (bảng, khóa, chỉ mục), cách mô hình hóa theo mẫu truy cập (bao gồm thiết kế một-bảng), cách hoạt động của scale và chế độ dung lượng, và các mẫu thực tiễn để stream thay đổi vào kiến trúc hướng sự kiện.

Khái niệm cơ bản: Bảng, Item và Khóa chính

DynamoDB được tổ chức quanh vài khối xây dựng đơn giản, nhưng chi tiết quan trọng vì chúng quyết định cách bạn mô hình dữ liệu và tốc độ (và chi phí) của các yêu cầu.

Bảng, item và thuộc tính

Một table là vùng chứa ở cấp cao nhất. Mỗi bản ghi trong bảng là một item (tương tự một hàng), và mỗi item là một tập attributes (tương tự cột).

Khác với cơ sở dữ liệu quan hệ, các item trong cùng bảng không cần có chung các thuộc tính. Một item có thể có {status, total, customerId}, trong khi item khác có {status, shipmentTracking}—DynamoDB không yêu cầu schema cố định.

Khóa chính: đơn vs tổng hợp

Mỗi item được xác định duy nhất bởi một primary key, và DynamoDB hỗ trợ hai loại:

  • Khóa chính đơn (chỉ partition key): một thuộc tính xác định duy nhất mỗi item.
  • Khóa chính tổng hợp (partition key + sort key): nhiều item có thể chia sẻ cùng partition key, trong khi sort key phân biệt chúng và định thứ tự trong phân vùng đó.

Trong thực tế, khóa tổng hợp cho phép các mẫu truy cập “nhóm” như “tất cả đơn hàng của một khách, mới nhất trước”.

Query vs Scan (tổng quan)

Query đọc item theo khóa chính (hoặc khóa của chỉ mục). Nó nhắm tới một partition key cụ thể và có thể lọc theo khoảng sort key—đây là con đường hiệu quả, được ưu tiên.

Scan duyệt toàn bộ bảng (hoặc chỉ mục) rồi lọc. Nó dễ bắt đầu, nhưng thường chậm và tốn kém ở quy mô lớn.

Những giới hạn cần nhớ

Một vài ràng buộc bạn sẽ gặp sớm:

  • Kích thước item tối đa: 400 KB.
  • Loại thuộc tính: scalar (string/number/binary/boolean/null), sets, lists và maps.
  • Thuộc tính khóa phải là scalar (không được dùng list/map làm partition hoặc sort key).

Những nền tảng này thiết lập tất cả phần còn lại: mẫu truy cập, lựa chọn chỉ mục và đặc tính hiệu năng.

Mô hình dữ liệu của DynamoDB: Key-Value và Document

DynamoDB thường được mô tả vừa là kho key-value vừa là cơ sở dữ liệu document. Điều đó đúng, nhưng nên hiểu rõ ý nghĩa từng kiểu trong thiết kế hàng ngày.

Truy cập theo key vs item kiểu document

Về cốt lõi, bạn lấy dữ liệu theo key. Cung cấp giá trị khóa chính và DynamoDB trả về một item duy nhất. Tra cứu theo khóa là điều mang lại độ trễ thấp ổn định cho nhiều khối lượng công việc.

Đồng thời, một item có thể chứa các thuộc tính lồng nhau (maps và lists), khiến nó giống cơ sở dữ liệu document: bạn có thể lưu payload có cấu trúc mà không cần định nghĩa schema cứng trước.

Mô hình cấu trúc JSON lồng nhau trong item

Items phù hợp tự nhiên với dữ liệu kiểu JSON:

  • Maps đại diện cho đối tượng (ví dụ profile.name, profile.address).
  • Lists đại diện cho mảng (ví dụ hành động gần đây, tags).

Điều này phù hợp khi một thực thể thường được đọc toàn bộ—như hồ sơ người dùng, giỏ hàng, hoặc gói cấu hình.

Khi nào nên denormalize (và vì sao phổ biến)

DynamoDB không hỗ trợ join phía máy chủ. Nếu ứng dụng cần lấy “một đơn và các dòng hàng và trạng thái vận chuyển” trong một lần đọc, bạn thường sẽ denormalize: sao chép một số thuộc tính sang nhiều item, hoặc nhúng các cấu trúc nhỏ vào trong item.

Đánh đổi so với chuẩn hóa quan hệ

Denormalize làm tăng độ phức tạp khi ghi và có thể gây fan-out khi cập nhật. Đổi lại là giảm số lần round trip và đọc nhanh hơn—thường là yếu tố quyết định trong hệ thống có thể mở rộng.

Partition Key và Sort Key: Thiết kế theo mẫu truy cập

Các truy vấn DynamoDB nhanh nhất là những truy vấn bạn có thể diễn đạt là “cho tôi phân vùng này” (và tùy chọn “trong phân vùng này, cho tôi khoảng này”). Vì vậy, chọn khóa chủ yếu dựa trên cách bạn đọc dữ liệu, chứ không chỉ là cách lưu.

Partition key: phân phối và đọc dự đoán

Partition key quyết định item sẽ nằm trên phân vùng vật lý nào. DynamoDB băm giá trị này để phân tán dữ liệu và lưu lượng. Nếu nhiều yêu cầu tập trung vào một vài giá trị partition key, bạn có thể tạo ra phân vùng “nóng” và chạm giới hạn throughput dù bảng nhìn chung rảnh.

Partition key tốt:

  • Có độ phân tán cao (nhiều giá trị khác nhau)
  • Phù hợp với mẫu truy cập thường xuyên (để đọc trực tiếp, không lọc)
  • Tránh các giá trị sẽ trở nên “phổ biến” (ví dụ một hằng như "GLOBAL")

Sort key: truy vấn theo khoảng và nhóm thực thể

Với sort key, các item chia sẻ cùng partition key được lưu cạnh nhau và sắp xếp theo sort key. Điều này cho phép hiệu quả:

  • Truy vấn theo khoảng (BETWEEN, begins_with)
  • Đọc theo thứ tự thời gian (mới nhất trước bằng scan đảo ngược)
  • Nhóm thực thể (nhiều loại item dưới một partition key)

Một mẫu phổ biến là ghép sort key, như TYPE#id hoặc TS#2025-12-22T10:00:00Z, để hỗ trợ nhiều hình dạng truy vấn mà không cần thêm bảng.

Ánh xạ các mẫu truy cập thông dụng vào khóa

  • Lấy theo ID: PK = USER#<id> (GetItem đơn giản)
  • Liệt kê theo người dùng: PK = USER#<id>, SK begins_with ORDER# (hoặc SK = CREATED_AT#...)
  • Chuỗi thời gian: PK = DEVICE#<id>, SK = TS#<timestamp> với BETWEEN cho cửa sổ thời gian

Cách lựa chọn khóa ảnh hưởng tới hiệu năng và khả năng mở rộng

Nếu partition key của bạn phù hợp với các truy vấn có khối lượng cao nhất và phân phối đều, bạn sẽ có đọc/ghi độ trễ thấp ổn định. Nếu không, bạn sẽ bù bằng scans, filters, hoặc chỉ mục thêm—mỗi thứ đều tăng chi phí và rủi ro khoá nóng.

Chỉ mục phụ: GSI và LSI giải thích

Chỉ mục phụ cung cấp cho DynamoDB đường truy vấn thay thế bên cạnh khóa chính của bảng. Thay vì thay đổi bảng gốc mỗi khi xuất hiện mẫu truy cập mới, bạn có thể thêm chỉ mục tái khóa cùng một items cho truy vấn khác.

GSI vs LSI: khác nhau ở đâu?

Global Secondary Index (GSI) có partition key riêng (và sort key tùy chọn) có thể hoàn toàn khác với bảng gốc. Nó là “toàn cục” vì phủ khắp mọi phân vùng của bảng và có thể thêm hoặc xóa bất kỳ lúc nào. Dùng GSI khi bạn cần mẫu truy cập mới không phù hợp với thiết kế khóa ban đầu—ví dụ truy vấn đơn hàng theo customerId khi bảng được khóa bởi orderId.

Local Secondary Index (LSI) chia sẻ partition key với bảng gốc nhưng dùng sort key khác. LSI phải được định nghĩa khi tạo bảng. Chúng hữu ích khi bạn muốn nhiều thứ tự sắp xếp trong cùng một nhóm thực thể (cùng partition key), như lấy đơn hàng của khách theo createdAt so với status.

Projections: những gì được sao chép vào chỉ mục

Projection quyết định thuộc tính nào DynamoDB lưu trong chỉ mục:

  • KEYS_ONLY: chi phí lưu trữ thấp nhất, nhưng bạn thường cần đọc thêm từ bảng gốc.
  • INCLUDE: sao chép chỉ các thuộc tính bạn thường trả về.
  • ALL: đơn giản nhất, nhưng có thể làm tăng lưu trữ và chi phí ghi.

Ghi khuếch đại (chi phí ẩn)

Mỗi ghi vào bảng gốc có thể kích hoạt ghi vào một hoặc nhiều chỉ mục. Thêm GSI và mở rộng projection làm tăng chi phí ghi và tiêu thụ dung lượng. Hãy lập kế hoạch chỉ mục quanh các mẫu truy cập ổn định và giữ projection nhỏ khi có thể.

Chế độ dung lượng và hành vi scale

Design around Streams events
Draft an event-driven flow and wire handlers around change events with a chat-built backend.
Build Workflow

DynamoDB yêu cầu chọn: On-Demand hoặc Provisioned. Cả hai đều có thể đạt throughput rất cao, nhưng hành vi với lưu lượng thay đổi khác nhau.

On-Demand vs Provisioned: chọn như thế nào

On-Demand đơn giản: bạn trả theo yêu cầu và DynamoDB tự động đáp ứng tải biến đổi. Phù hợp cho lưu lượng không thể dự đoán, sản phẩm giai đoạn đầu, và workloads có đột biến mà bạn không muốn quản lý mục tiêu dung lượng.

Provisioned là lập kế hoạch dung lượng: bạn chỉ định (hoặc auto-scale) throughput đọc và ghi và có giá dự đoán hơn cho mức sử dụng ổn định. Thường rẻ hơn cho workloads ổn định và cho đội có thể dự báo demanda.

Dung lượng đọc/ghi trong thực tế

Provisioned throughput đo bằng:

  • RCUs (Read Capacity Units): xấp xỉ một lần đọc mạnh (strongly consistent) mỗi giây cho tới 4 KB (hoặc hai lần đọc eventually consistent).
  • WCUs (Write Capacity Units): xấp xỉ một lần ghi mỗi giây cho tới 1 KB.

Kích thước item và mẫu truy cập quyết định chi phí thực tế: item lớn, strong consistency, và scans có thể tiêu thụ dung lượng nhanh.

Cơ bản về auto scaling (và giới hạn)

Auto scaling điều chỉnh RCUs/WCUs provisioned theo mục tiêu sử dụng. Nó hữu ích với tăng trưởng dần và chu kỳ dự đoán, nhưng không tức thời. Đột biến đột ngột vẫn có thể bị throttle nếu dung lượng chưa kịp nâng, và nó không sửa khóa nóng do tập trung lưu lượng vào một phân vùng.

DAX: cache cho workloads nhiều đọc

DynamoDB Accelerator (DAX) là cache bộ nhớ trong giúp giảm độ trễ đọc và giảm tải cho các lần đọc lặp (ví dụ trang sản phẩm phổ biến, tra session, bảng xếp hạng). Hiệu quả nhất khi nhiều client lặp lại yêu cầu cùng item; nó không giúp cho workloads nhiều ghi và không thay thế việc thiết kế khóa cẩn thận.

Tính nhất quán, giao dịch và đúng đắn dữ liệu

DynamoDB cho phép bạn đánh đổi sự đảm bảo đọc lấy giá trị mới nhất với độ trễ và chi phí, nên cần rõ ràng về khái niệm “đúng” cho từng thao tác.

Đọc eventually consistent vs strongly consistent

Mặc định, GetItem và Query là eventually consistent: bạn có thể thấy giá trị cũ ngay sau khi ghi. Điều này thường chấp nhận được cho feed, danh mục sản phẩm và các view đọc nhiều.

Với strongly consistent reads (tùy chọn cho đọc từ bảng gốc trong cùng region), DynamoDB đảm bảo bạn thấy ghi mới nhất đã được xác nhận. Strong consistency tốn nhiều RCU hơn và có thể làm tăng độ trễ đuôi, nên chỉ dùng cho các đọc thực sự quan trọng.

Khi nào strong consistency quan trọng

Strong consistency hữu ích cho các lần đọc quyết định hành động không thể hồi lại:

  • Kiểm tra tồn kho trước khi xác nhận đơn hàng
  • Đọc cờ ủy quyền trước khi cấp quyền
  • Lấy trạng thái hiện tại của workflow trước khi thực thi bước tiếp theo

Với counters, cách an toàn nhất thường không phải là “đọc mạnh rồi ghi”, mà là cập nhật nguyên tử (ví dụ UpdateItem với ADD) để tránh mất increments.

Giao dịch đọc/ghi

Giao dịch DynamoDB (TransactWriteItems, TransactGetItems) cung cấp ACID cho tối đa 25 items. Hữu ích khi bạn phải cập nhật nhiều item cùng lúc—như ghi đơn và giữ tồn kho—hoặc đảm bảo các bất biến không chấp nhận trạng thái trung gian.

Idempotency cho retry an toàn

Retry là bình thường trong hệ phân tán. Hãy làm ghi idempotent để retry không gây nhân bản hiệu ứng:

  • Dùng client request token (idempotency key) lưu cùng kết quả
  • Ép tính duy nhất bằng ConditionExpression (ví dụ: “only create if attribute_not_exists”)
  • Ưu tiên cập nhật nguyên tử hơn vòng read-modify-write

Đúng đắn trong DynamoDB chủ yếu là chọn mức độ nhất quán phù hợp và thiết kế thao tác sao cho retry không phá hỏng dữ liệu.

Phân vùng, khoá nóng và đột biến lưu lượng

DynamoDB lưu dữ liệu qua nhiều phân vùng vật lý. Mỗi phân vùng có throughput hữu hạn cho đọc và ghi, cùng giới hạn dung lượng lưu trữ. Partition key quyết định item nằm ở đâu; nếu quá nhiều yêu cầu nhắm vào cùng một giá trị partition key (hoặc vài giá trị), phân vùng đó sẽ trở thành cổ chai.

Tại sao phân vùng nóng xảy ra

Phân vùng nóng thường do chọn khóa tập trung lưu lượng: một partition key “global” như USER#1, TENANT#default, hoặc STATUS#OPEN, hoặc mẫu theo thời gian khi mọi người đều ghi vào “bây giờ” dưới một khóa.

Triệu chứng của khoá nóng và lưu lượng không đều

Bạn thường thấy:

  • Throttling (ProvisionedThroughputExceededException) cho một tập con khóa
  • Độ trễ cao và đột biến cho vài mẫu truy cập trong khi các truy vấn khác vẫn nhanh
  • Metrics CloudWatch cho thấy tiêu thụ dung lượng không đều và các đột biến

Kỹ thuật giảm thiểu

Thiết kế để phân phối trước, rồi mới nghĩ sự tiện lợi khi truy vấn:

  • Thiết kế khóa: đảm bảo partition key có độ phân tán cao (ví dụ TENANT#<id> thay vì một hằng)
  • Sharding ghi: thêm hậu tố/tiền tố ngẫu nhiên hoặc hash như ORDER#<id>#<shard> để trải đều lên N shard, sau đó truy vấn qua các shard khi cần
  • Time buckets: gom theo giờ/ngày (METRIC#2025-12-22T10) để tránh “tất cả ghi vào item mới nhất”

Xử lý workloads đột biến

Với đột biến không dự đoán, on-demand có thể hấp thụ đợt tăng (trong giới hạn dịch vụ). Với provisioned, dùng auto scaling và triển khai client-side exponential backoff với jitter khi throttle để tránh retry đồng bộ làm khuếch đại đợt đột biến.

Mẫu mô hình dữ liệu cho hệ thống có thể mở rộng

Test single-table ideas quickly
Generate a single-table design skeleton and iterate on PK SK conventions without weeks of setup.
Build Now

Mô hình dữ liệu DynamoDB bắt đầu từ mẫu truy cập, không phải từ sơ đồ ER. Bạn thiết kế khóa để các truy vấn cần thiết trở thành các thao tác Query nhanh, mọi thứ khác hoặc được tránh hoặc được xử lý bất đồng bộ.

Thiết kế một-bảng (và vì sao đội thích)

“Thiết kế một-bảng” nghĩa là lưu nhiều loại thực thể (users, orders, messages) vào một bảng duy nhất và dùng quy ước khóa thống nhất để lấy dữ liệu liên quan trong một Query. Điều này giảm round-trip giữa các thực thể và giữ độ trễ ổn định.

Cách tiếp cận phổ biến là khóa tổng hợp:

  • PK nhóm phân vùng logic (ví dụ USER#123)
  • SK sắp xếp item trong nhóm đó (ví dụ PROFILE, ORDER#2025-12-01, MSG#000123)

Điều này cho phép bạn lấy “mọi thứ cho một người dùng” hoặc “chỉ đơn hàng cho người dùng” bằng cách chọn tiền tố sort-key.

Quan hệ: adjacency list và nhiều-nhiều

Cho các quan hệ giống đồ thị, adjacency list hoạt động tốt: lưu cạnh dưới dạng items.

  • PK = USER#123, SK = FOLLOWS#USER#456

Để hỗ trợ truy vấn ngược hoặc nhiều-nhiều thực sự, thêm một item cạnh đảo ngược hoặc project lên GSI, tùy theo các đường đọc.

Chuỗi thời gian: bucket + sort key + TTL

Với sự kiện và metric, tránh phân vùng không giới hạn bằng cách gom theo bucket:

  • PK = DEVICE#9#2025-12-22 (device + ngày)
  • SK = TS#1734825600 (timestamp)

Dùng TTL để hết hạn điểm cũ tự động, và giữ các aggregates (rollup giờ/ngày) như item riêng cho dashboard nhanh.

Nếu bạn muốn ôn tập sâu hơn về quy ước khóa, xem /blog/partition-key-and-sort-key-design.

Streams và kiến trúc hướng sự kiện

DynamoDB Streams là feed thay đổi dữ liệu (CDC) tích hợp. Khi bật trên bảng, mỗi insert, update hoặc delete tạo một bản ghi stream mà các consumer hạ nguồn có thể phản ứng—không cần polling bảng.

Những gì cơ bản về DynamoDB Streams

Một record stream chứa khóa và (tùy chọn) ảnh cũ và/hoặc mới của item, tùy loại view bạn chọn (keys only, new image, old image, both). Các bản ghi nhóm theo shards, bạn đọc tuần tự.

Xây dựng workflow hướng sự kiện

Mô hình phổ biến là DynamoDB Streams → AWS Lambda, trong đó mỗi lô record kích hoạt một function. Các consumer khác cũng có thể (custom consumer, hoặc đẩy vào hệ thống analytics/logging).

Workflow điển hình bao gồm:

  • Materialized views: ghi một bảng read-model denormalized khi bảng nguồn thay đổi.
  • Cache invalidation: hết hạn hoặc làm mới item trong Redis/ElastiCache sau các ghi.
  • Audit logs: thêm sự kiện thay đổi bất biến vào bảng audit hoặc kho ngoài.

Điều này giữ bảng chính tối ưu cho đọc/ghi độ trễ thấp trong khi đẩy công việc dẫn xuất ra các consumer bất đồng bộ.

Thứ tự, retry và đúng đắn

Streams cung cấp xử lý theo thứ tự trên mỗi shard (thường tương quan với partition key), nhưng không có thứ tự toàn cục giữa các khóa. Giao hàng là at-least-once, vì vậy có thể có trùng lặp.

Để xử lý an toàn:

  • Làm handler idempotent (ví dụ upsert theo khóa chính, dùng ghi có điều kiện, hoặc lưu ID sự kiện đã xử lý)
  • Dự kiến retry và thất bại lô một phần; dùng DLQ/đích on-failure khi có thể
  • Giữ side effects (email, thanh toán) sau lớp deduplication hoặc biện pháp giao dịch an toàn

Khi thiết kế theo các đảm bảo này, Streams có thể biến DynamoDB thành xương sống đáng tin cậy cho hệ thống hướng sự kiện.

Độ tin cậy, sao lưu và quan sát

DynamoDB được thiết kế cho độ khả dụng cao bằng cách trải dữ liệu qua nhiều Availability Zone trong một region. Với hầu hết đội, lợi ích thực tế về độ tin cậy đến từ chiến lược sao lưu rõ ràng, hiểu các tùy chọn nhân bản, và giám sát những metric đúng.

Sao lưu: on-demand vs point-in-time recovery

On-demand backups là snapshot thủ công (hoặc tự động) bạn tạo khi muốn một điểm khôi phục xác định—trước migration, sau release, hoặc trước khi chạy backfill lớn. Tốt cho các khoảnh khắc “đánh dấu”.

Point-in-time recovery (PITR) liên tục ghi nhận thay đổi để bạn có thể khôi phục bảng về bất kỳ giây nào trong cửa sổ giữ. PITR là mạng lưới an toàn cho xóa nhầm, deploy lỗi, hoặc ghi sai trượt qua validation.

Nhân bản và tùy chọn đa vùng

Nếu cần khả năng chịu lỗi đa vùng hoặc đọc với độ trễ thấp gần người dùng, Global Tables sao chép dữ liệu qua các region đã chọn. Chúng đơn giản hóa kế hoạch failover, nhưng đem theo độ trễ sao chép giữa vùng và các cân nhắc giải quyết xung đột—vì vậy giữ rõ ràng mẫu ghi và quyền sở hữu item.

Giám sát thiết yếu

Ít nhất, cảnh báo về:

  • Độ trễ (p95/p99) cho đọc và ghi
  • Yêu cầu bị throttle và lỗi hệ thống
  • Tiêu thụ dung lượng (và khoảng trống so với provisioned)

Những tín hiệu này thường bộc lộ vấn đề phân vùng nóng, dung lượng chưa đủ, hoặc mẫu truy cập bất ngờ.

Playbook sự cố

Với throttling, trước tiên xác định mẫu truy cập gây ra, sau đó giảm thiểu bằng cách tạm chuyển sang on-demand hoặc tăng provisioned capacity, và cân nhắc sharding cho hot keys.

Với gián đoạn một phần hoặc lỗi tăng, giảm phạm vi ảnh hưởng: vô hiệu hóa lưu lượng không quan trọng, retry với backoff có jitter, và degrade nhẹ (ví dụ phục vụ đọc từ cache) cho tới khi bảng ổn định.

Bảo mật và kiểm soát truy cập

Ship a mobile companion app
Build a Flutter client for your DynamoDB service to test latency and offline UX quickly.
Try Mobile

Bảo mật DynamoDB chủ yếu là siết chặt ai có thể gọi API nào, từ đâu, và trên khóa nào. Vì bảng có thể chứa nhiều loại thực thể (và đôi khi nhiều tenant), kiểm soát truy cập nên được thiết kế song song với mô hình dữ liệu.

IAM permissions: nguyên tắc ít quyền nhất

Bắt đầu với chính sách IAM dựa trên danh tính giới hạn hành động (ví dụ dynamodb:GetItem, Query, PutItem) xuống tập nhỏ nhất và giới hạn theo ARNs của bảng.

Để kiểm soát chi tiết hơn, dùng dynamodb:LeadingKeys để hạn chế truy cập theo giá trị partition key—hữu ích khi một service hoặc tenant chỉ được đọc/ghi trong keyspace của chính mình.

Mã hóa: điều cần kiểm tra

DynamoDB mã hóa dữ liệu khi lưu mặc định bằng khóa do AWS sở hữu hoặc khóa KMS do khách hàng quản lý. Nếu có yêu cầu tuân thủ, xác minh:

  • Bảng được cấu hình với KMS key mong muốn
  • Role gọi có quyền KMS cần thiết (và không quá nhiều quyền)

Với mã hóa trong khi truyền, đảm bảo client dùng HTTPS (SDK AWS mặc định đã dùng). Nếu bạn terminate TLS ở proxy, xác nhận đoạn giữa proxy và DynamoDB vẫn được mã hóa.

Kiểm soát mạng: giảm đường rò rỉ dữ liệu

Dùng VPC Gateway Endpoint cho DynamoDB để traffic ở lại trên mạng AWS và bạn có thể áp chính sách endpoint để giới hạn truy cập. Kết hợp với kiểm soát egress (NACLs, security groups, routing) để tránh đường dẫn “bất kỳ thứ gì đều có thể ra internet công cộng”.

Thiết kế đa tenant và mẫu cô lập

Với bảng chia sẻ, chèn tenant identifier vào partition key (ví dụ TENANT#<id>), rồi thực thi isolation bằng IAM condition trên dynamodb:LeadingKeys.

Nếu cần cách ly mạnh hơn, cân nhắc bảng riêng cho từng tenant hoặc môi trường, và chỉ dùng bảng chia sẻ khi đơn giản trong vận hành và chi phí là ưu tiên hơn phạm vi ảnh hưởng nhỏ hơn.

Tối ưu chi phí cho DynamoDB

DynamoDB thường “rẻ khi bạn rõ ràng, đắt khi bạn mơ hồ.” Chi phí theo mẫu truy cập, nên tối ưu tốt nhất bắt đầu bằng làm rõ các mẫu đó.

Hiểu các yếu tố chi phí

Hóa đơn của bạn chủ yếu bị ảnh hưởng bởi:

  • Đọc và ghi (RCUs/WCUs ở chế độ provisioned, request units ở on-demand)
  • Lưu trữ (dữ liệu bảng cộng với kích thước item)
  • Chỉ mục phụ (mỗi GSI có chi phí ghi và lưu trữ riêng)
  • Streams (yêu cầu đọc trên các record stream và consumer hạ lưu)

Một bất ngờ phổ biến: mỗi ghi vào bảng cũng là một ghi vào mỗi GSI bị ảnh hưởng, nên “thêm một chỉ mục” có thể nhân chi phí ghi.

Thiết kế khóa để tránh lãng phí

Thiết kế khóa tốt giảm nhu cầu các thao tác tốn kém. Nếu bạn thường xuyên dùng Scan, bạn đang trả tiền để đọc dữ liệu rồi bỏ đi.

Ưu tiên:

  • Query theo partition key (và tùy chọn điều kiện sort key)
  • Projection hẹp trong GSI (chỉ project thuộc tính bạn thực sự cần)

Nếu một mẫu truy cập hiếm, cân nhắc phục vụ nó qua bảng riêng, job ETL, hoặc read-model cache thay vì GSI vĩnh viễn.

Kiểm soát lưu trữ với TTL và lifecycle

Dùng TTL để xóa tự động các item ngắn hạn (session, token tạm thời, trạng thái workflow trung gian). Điều này giảm lưu trữ và giữ chỉ mục nhỏ hơn theo thời gian.

Với dữ liệu ghi dồn (events, logs), kết hợp TTL với thiết kế sort-key cho phép bạn query “chỉ gần đây”, tránh chạm tới lịch sử lạnh thường xuyên.

Chọn dung lượng phù hợp và tránh đột biến vô tình

Ở chế độ provisioned, đặt baseline thận trọng và scale bằng auto scaling dựa trên metric thực. Ở on-demand, theo dõi các mẫu không hiệu quả (item lớn, client chatty) làm tăng volume yêu cầu.

Xem Scan như lựa chọn cuối cùng—khi thật sự cần xử lý toàn bảng, chạy vào giờ thấp điểm hoặc như batch có phân trang và backoff.

Khi nào nên chọn DynamoDB (và khi nào không)

DynamoDB tỏa sáng khi ứng dụng của bạn có thể biểu diễn bằng một tập các mẫu truy cập rõ ràng và bạn cần độ trễ thấp ổn định ở quy mô lớn. Nếu bạn có thể mô tả đọc và ghi trước (theo partition key, sort key, và vài chỉ mục), DynamoDB thường là một trong những cách dễ vận hành nhất để có store sẵn sàng cao.

Phù hợp tuyệt vời

DynamoDB là lựa chọn mạnh khi bạn có:

  • Truy vấn dự đoán (lấy hồ sơ người dùng, liệt kê đơn hàng của người dùng theo thời gian, tải session theo ID)
  • Throughput ghi cao hoặc lưu lượng đột biến bạn không muốn can thiệp
  • Cần scale ngang mà không quản lý server
  • Thiết kế hướng sự kiện sử dụng Streams để kích hoạt công việc hạ nguồn

Khi nên cân nhắc lựa chọn khác

Tìm lựa chọn khác nếu yêu cầu cốt lõi của bạn bao gồm:

  • Join phức tạp giữa nhiều thực thể hoặc duyệt quan hệ thường xuyên
  • Truy vấn ad hoc và analytics thay đổi hàng tuần (group-bys, lọc khám phá)
  • Tìm kiếm văn bản nặng và xếp hạng độ liên quan mà không có chỉ mục ngoài

Cách tiếp cận hybrid hoạt động tốt

Nhiều đội giữ DynamoDB cho các đọc/ghi “nóng”, rồi thêm:

  • S3 + Athena cho analytics và báo cáo lịch sử
  • OpenSearch (hoặc tương tự) cho tìm kiếm full-text và faceting
  • Lớp cache khi một vài khóa rất nặng về đọc

Ghi chú prototype: rút ngắn đường từ model đến app

Nếu bạn đang kiểm chứng mẫu truy cập và quy ước một-bảng, tốc độ quan trọng. Các đội đôi khi prototype service và UI trên Koder.ai (một nền tảng vibe-coding tạo web, server, và mobile app từ chat) rồi lặp trên thiết kế khóa DynamoDB khi các đường truy vấn thực xuất hiện. Dù backend sản xuất khác, prototype end-to-end nhanh giúp lộ ra truy vấn nào nên là Query và truy vấn nào sẽ vô tình thành Scan tốn kém.

Checklist quyết định nhanh

Xác thực: (1) các truy vấn hàng đầu đã biết và dựa trên khóa, (2) yêu cầu về đúng đắn khớp mô hình nhất quán, (3) hiểu kích thước item và tăng trưởng dự kiến, và (4) mô hình chi phí (on-demand vs provisioned + autoscaling) phù hợp ngân sách của bạn.

Câu hỏi thường gặp

What is DynamoDB, and when is it a good choice?

DynamoDB là một cơ sở dữ liệu NoSQL được quản lý hoàn toàn trên AWS, thiết kế cho các hoạt động cần độ trễ đọc/ghi thấp ổn định ở quy mô rất lớn. Các đội chọn dùng khi họ có thể xác định các mẫu truy cập theo khóa (lấy theo ID, liệt kê theo chủ sở hữu, truy vấn theo khoảng thời gian) và muốn tránh việc vận hành cơ sở hạ tầng cơ sở dữ liệu.

Nó đặc biệt phổ biến trong microservices, ứng dụng serverless, và các hệ thống hướng sự kiện.

What are tables, items, and attributes in DynamoDB?

Một bảng chứa items (tương tự hàng). Mỗi item là một tập hợp linh hoạt các attributes (tương tự cột) và có thể bao gồm dữ liệu lồng nhau.

DynamoDB phù hợp khi một yêu cầu thường cần “toàn bộ thực thể”, vì item có thể chứa maps và lists (cấu trúc giống JSON).

What’s the difference between a simple primary key and a composite primary key?

Một partition key một mình xác định duy nhất một item (khóa chính đơn giản). Partition key + sort key (khóa tổng hợp) cho phép nhiều item chia sẻ cùng partition key trong khi vẫn được phân biệt duy nhất và có thứ tự theo sort key.

Khóa tổng hợp hỗ trợ các mẫu như:

  • “Tất cả đơn hàng của một khách hàng”
  • “Sự kiện cho một thiết bị trong khoảng thời gian”
When should I use Query vs Scan?

Dùng Query khi bạn biết partition key (và tùy chọn điều kiện sort key). Đó là con đường nhanh và có thể mở rộng.

Dùng Scan chỉ khi bạn thực sự cần đọc toàn bộ bảng; nó quét toàn bộ bảng hoặc chỉ mục rồi lọc sau, thường chậm và tốn kém.

Nếu bạn thường xuyên phải scan, đó là dấu hiệu thiết kế khóa hoặc chỉ mục cần được điều chỉnh.

What are GSIs and LSIs, and how do I choose?

Chỉ mục phụ cung cấp đường truy vấn thay thế.

  • GSI (Global Secondary Index): có thể dùng partition key khác (và sort key tùy chọn) so với bảng gốc; có thể thêm sau khi tạo bảng.
  • LSI (Local Secondary Index): chia sẻ cùng partition key với bảng gốc nhưng dùng sort key khác; phải định nghĩa khi tạo bảng.

Chỉ mục tăng chi phí ghi vì mỗi ghi có thể được sao chép vào chỉ mục.

How do I choose between On-Demand and Provisioned capacity?

Chọn On-Demand nếu lưu lượng không thể dự đoán, có tính đột biến, hoặc bạn không muốn quản lý dung lượng. Bạn trả theo yêu cầu.

Chọn Provisioned nếu lưu lượng ổn định/dự đoán và bạn muốn chi phí kiểm soát hơn. Kết hợp với auto scaling, nhưng lưu ý nó không phản ứng tức thì với các đột biến đột ngột.

What consistency options does DynamoDB offer, and when do they matter?

Mặc định, các lần đọc là eventually consistent, có thể đọc giá trị cũ ngay sau khi ghi.

Dùng đọc strongly consistent (khi có) cho các kiểm tra cần đảm bảo luôn cập nhật, ví dụ cổng ủy quyền hoặc bước chuyển trạng thái workflow.

Để đảm bảo đúng dưới cạnh tranh, ưu tiên cập nhật nguyên tử (ví dụ ADD hoặc ConditionExpression) hơn là vòng đọc-sửa-ghi.

When should I use DynamoDB transactions?

Transactions (TransactWriteItems, TransactGetItems) cung cấp giao dịch ACID trên tối đa 25 items.

Dùng khi bạn phải cập nhật nhiều item cùng lúc (ví dụ: tạo đơn và giữ hàng) hoặc cần bảo đảm tính toàn vẹn không chấp nhận trạng thái trung gian.

Chúng tốn kém hơn và làm tăng độ trễ, nên chỉ dùng cho luồng thực sự cần thiết.

What are hot keys/partitions, and how can I avoid them?

Hot partition xảy ra khi quá nhiều yêu cầu nhắm vào cùng một giá trị partition key (hoặc vài giá trị), gây throttling dù bảng vẫn nhàn rỗi ở phần còn lại.

Các biện pháp khắc phục phổ biến:

  • Chọn partition key có độ phân tán cao
  • Thêm (phần đuôi/đầu ngẫu nhiên/hash)
How do DynamoDB Streams support event-driven architectures?

Bật DynamoDB Streams để nhận luồng thay đổi cho insert, update, delete. Mô hình phổ biến là Streams → Lambda để kích hoạt công việc hạ lưu.

Những bảo đảm quan trọng cần thiết kế:

  • Thứ tự là trên mỗi shard (không có thứ tự toàn cục)
  • Giao hàng là at-least-once (có thể trùng lặp)

Hãy làm cho bộ tiêu thụ (upsert theo khóa, dùng ghi có điều kiện, hoặc lưu ID sự kiện đã xử lý).

Mục lục
DynamoDB là gì và vì sao các đội chọn nóKhái niệm cơ bản: Bảng, Item và Khóa chínhMô hình dữ liệu của DynamoDB: Key-Value và DocumentPartition Key và Sort Key: Thiết kế theo mẫu truy cậpChỉ mục phụ: GSI và LSI giải thíchChế độ dung lượng và hành vi scaleTính nhất quán, giao dịch và đúng đắn dữ liệuPhân vùng, khoá nóng và đột biến lưu lượngMẫu mô hình dữ liệu cho hệ thống có thể mở rộngStreams và kiến trúc hướng sự kiệnĐộ tin cậy, sao lưu và quan sátBảo mật và kiểm soát truy cậpTối ưu chi phí cho DynamoDBKhi nào nên chọn DynamoDB (và khi nào không)Câu hỏi thường gặp
Chia sẻ
Koder.ai
Build your own app with Koder today!

The best way to understand the power of Koder is to see it for yourself.

Start FreeBook a Demo
sharding ghi
  • Dùng time buckets cho dữ liệu theo thời gian
  • Triển khai exponential backoff với jitter khi bị throttle
  • idempotent