Ngân hàng đề — AWS Certified Developer Associate
Tìm thấy 1356 câu.
A serverless application uses an AWS Lambda function, Amazon API Gateway API and an Amazon DynamoDB table. The Lambda function executes 10 times per second and takes 3 seconds to complete each execution.
How many concurrent executions will the Lambda function require?
-
A
10
-
B
12
-
C
3
-
D
30
Xem giải thích
Đáp án
D — 30 concurrent executions.
Vì sao đúng
Công thức concurrency của Lambda:
Concurrency = Số lần gọi mỗi giây × Thời lượng mỗi lần (giây)
Thay số từ đề:
10 lần/giây × 3 giây = 30
Trực giác đằng sau công thức: nếu mỗi lần gọi kéo dài 3 giây, thì tại một thời điểm bất kỳ, 3 giây gọi vừa qua đều đang còn chạy:
Giây 0: bắt đầu 10 hàm → đang chạy: 10
Giây 1: bắt đầu 10 hàm → đang chạy: 20
Giây 2: bắt đầu 10 hàm → đang chạy: 30
Giây 3: 10 hàm đầu kết thúc, 10 hàm mới bắt đầu → ổn định ở 30
Con số 30 nằm rất thoải mái trong hạn mức mặc định 1.000 concurrent executions mỗi Region — nên ứng dụng này không cần xin tăng gì.
Vì sao các phương án khác sai
- A. 10 — chỉ là số lần gọi mỗi giây, bỏ qua thời lượng. Nếu hàm chạy dưới 1 giây thì đáp án mới là 10.
- C. 3 — chỉ là thời lượng, bỏ qua tần suất gọi.
- B. 12 — không tương ứng với phép tính hợp lệ nào; có thể do cộng nhầm (10 + 3 hoặc tương tự).
Ghi nhớ
Công thức cần thuộc:
Concurrency = Requests/giây × Thời lượng (giây)
Vài ví dụ để kiểm tra trực giác: | Requests/giây | Thời lượng | Concurrency | |---|---|---| | 100 | 0,1 giây | 10 | | 10 | 3 giây | 30 | | 100 | 1 giây | 100 | | 20 | 20 giây | 400 | | 50 | 100 giây | 5.000 — vượt hạn mức mặc định |
Nhận xét quan trọng: thời lượng chạy ảnh hưởng tới concurrency mạnh ngang số request. Tối ưu thời gian chạy không chỉ giảm tiền mà còn giảm áp lực lên hạn mức.
Các hạn mức liên quan: | Hạn mức | Giá trị | |---|---| | Concurrency mặc định | 1.000 mỗi Region (tăng được) | | Burst concurrency | 500–3.000 tuỳ Region, sau đó tăng 500/phút | | Timeout tối đa | 15 phút |
Burst concurrency là chi tiết hay bị bỏ sót: khi tải tăng đột ngột, Lambda không nhảy thẳng lên hạn mức tối đa — nó khởi động một lượng burst ban đầu rồi tăng dần 500 mỗi phút. Nên với đỉnh rất dốc, bạn vẫn có thể bị throttle dù chưa chạm hạn mức tổng.
Ba metric cần theo dõi: | Metric | Ý nghĩa | |---|---| | ConcurrentExecutions | số hàm đang chạy | | Throttles | số lần bị từ chối vì hết concurrency | | UnreservedConcurrentExecutions | phần còn lại của tài khoản |
Và phân biệt hai khái niệm hay bị lẫn: | | Reserved concurrency | Provisioned concurrency | |---|---|---| | Tác dụng | đặt TRẦN + dành riêng slot | khởi tạo SẴN môi trường ấm | | Với cold start | không giúp | loại bỏ | | Chi phí | miễn phí | trả tiền giữ sẵn |
A mobile application has thousands of users. Each user may use multiple devices to access the application. The Developer wants to assign unique identifiers to these users regardless of the device they use.
Which of the below is the BEST method to obtain unique identifiers?
-
A
Implement developer-authenticated identities by using Amazon Cognito and get credentials for these identities
-
B
Assign IAM users and roles to the users. Use the unique IAM resource ID as the unique identifier
-
C
Use IAM-generated access key IDs for the users as the unique identifier, but do not store secret keys
-
D
Create a user table in Amazon DynamoDB with key-value pairs of users and their devices. Use these keys as unique identifiers
Xem giải thích
Đáp án
A — Cài đặt developer-authenticated identities bằng Amazon Cognito và lấy credential cho các danh tính đó.
Vì sao đúng
Yêu cầu: gán định danh duy nhất cho mỗi người dùng, bất kể họ dùng thiết bị nào.
Cognito identity pool cấp cho mỗi người dùng một identity ID duy nhất và không phụ thuộc thiết bị:
Người dùng đăng nhập trên điện thoại → identity ID: ap-southeast-1:abc-123-def
Cùng người dùng trên máy tính bảng → CÙNG identity ID: ap-southeast-1:abc-123-def
Developer-authenticated identities là cơ chế cho phép dùng hệ thống xác thực của riêng bạn mà vẫn lấy được identity ID và credential AWS:
# Backend của bạn xác thực người dùng theo cách riêng, rồi gọi:
response = cognito_identity.get_open_id_token_for_developer_identity(
IdentityPoolId='ap-southeast-1:xxxx-xxxx',
Logins={'login.congty.myapp': 'ma-nguoi-dung-noi-bo-12345'},
TokenDuration=3600
)
# → trả về IdentityId (duy nhất, ổn định) và OpenIdToken
Điểm mấu chốt: bạn ánh xạ định danh nội bộ của mình sang identity ID của Cognito. Người dùng đăng nhập từ thiết bị nào cũng ra cùng một identity ID.
Và identity ID dùng được luôn trong IAM policy để phân quyền theo từng người:
"Resource": "arn:aws:s3:::du-lieu/${cognito-identity.amazonaws.com:sub}/*"
Vì sao các phương án khác sai
- B. Gán IAM user và role cho từng người dùng — không mở rộng được: giới hạn 5.000 IAM user và 1.000 role mỗi tài khoản. Đề nói hàng nghìn người dùng — sát trần ngay, và ứng dụng di động luôn có thể tăng lên hàng chục nghìn. IAM dành cho nhân sự và ứng dụng, không dành cho người dùng cuối.
- C. Dùng access key ID làm định danh, không lưu secret key — sai về mọi mặt: vẫn vướng giới hạn 5.000 IAM user, và access key ID không phải định danh người dùng — nó là một phần của credential.
- D. Tạo bảng DynamoDB ánh xạ người dùng với thiết bị — tự dựng lại thứ Cognito làm sẵn, và không giải quyết vế credential: bạn có định danh, nhưng người dùng vẫn không truy cập được dịch vụ AWS. Phải tự viết thêm toàn bộ phần cấp quyền.
Ghi nhớ
Ba loại danh tính trong Cognito identity pool: | Loại | Nguồn xác thực | |---|---| | Authenticated (public provider) | Google, Facebook, Amazon, Apple, SAML, OIDC | | Developer-authenticated | hệ thống xác thực của riêng bạn | | Unauthenticated (guest) | không đăng nhập |
Loại thứ hai hữu ích khi bạn đã có hệ thống người dùng riêng và không muốn di trú sang Cognito user pool, nhưng vẫn muốn dùng identity pool để cấp credential AWS.
Quy trình developer-authenticated:
1. Người dùng đăng nhập vào hệ thống của BẠN
2. Backend của bạn gọi GetOpenIdTokenForDeveloperIdentity
→ nhận IdentityId + OpenIdToken
3. Trả token cho client
4. Client gọi GetCredentialsForIdentity → nhận credential AWS tạm thời
Bước 2 phải chạy ở backend với credential có quyền phù hợp — không bao giờ ở client.
| User Pool | Identity Pool | |
|---|---|---|
| Là gì | thư mục người dùng | bộ đổi danh tính lấy credential AWS |
| Phát ra | JWT | credential AWS tạm thời |
| Định danh ổn định qua thiết bị | ✅ (sub) |
✅ (identity ID) |
| Gọi thẳng S3/DynamoDB | ❌ | ✅ |
Và một tính năng liên quan rất hữu ích: MergeDeveloperIdentities cho phép gộp hai identity ID làm một — dùng khi người dùng ban đầu ở chế độ khách rồi mới đăng ký tài khoản, và bạn muốn giữ lại dữ liệu họ đã tạo.
A retail organization stores stock information in an Amazon RDS database. An application reads and writes data to the database. A Developer has been asked to provide read access to the database from a reporting application in another region.
Which configuration would provide BEST performance for the reporting application without impacting the performance of the main database?
-
A
Implement a cross-region read replica in the region where the reporting application will run
-
B
Implement a cross-region multi-AZ deployment in the region where the reporting application will run
-
C
Create a snapshot of the database and create a new database from the snapshot in the region where the reporting application will run
-
D
Implement a read replica in another AZ and configure the reporting application to connect to the read replica using a VPN connection
Xem giải thích
Đáp án
A — Dựng cross-region read replica ở Region nơi ứng dụng báo cáo chạy.
Vì sao đúng
Đề nêu hai yêu cầu, và cross-region read replica đáp ứng cả hai:
- Hiệu năng tốt nhất cho ứng dụng báo cáo ở Region khác
- Không ảnh hưởng hiệu năng của CSDL chính
Read replica là bản sao chỉ đọc, và đặt nó cùng Region với ứng dụng báo cáo mang lại hai lợi ích cùng lúc:
Region A (chính) Region B (báo cáo)
┌──────────────────┐ nhân bản ┌──────────────────┐
│ RDS primary │ ─────────────→│ Read replica │
│ đọc + ghi │ bất đồng bộ │ chỉ đọc │
└──────────────────┘ └──────────────────┘
↑ ↑
Ứng dụng chính Ứng dụng báo cáo
(độ trễ thấp, cùng Region)
| Yêu cầu | Cách đáp ứng |
|---|---|
| Hiệu năng cho ứng dụng báo cáo | truy vấn cục bộ, không qua Internet xuyên lục địa |
| Không ảnh hưởng CSDL chính | truy vấn báo cáo chạy trên replica, không chạm primary |
aws rds create-db-instance-read-replica \
--db-instance-identifier replica-bao-cao \
--source-db-instance-identifier arn:aws:rds:ap-southeast-1:123456789012:db:csdl-chinh \
--region us-east-1
Điểm quan trọng thứ hai đáng nhấn mạnh: truy vấn báo cáo thường rất nặng (quét nhiều dòng, tổng hợp). Chạy chúng trên primary sẽ làm chậm ứng dụng chính — tách sang replica là cách chuẩn để cô lập hai loại tải.
Vì sao các phương án khác sai
- B. Cross-region Multi-AZ deployment — tự mâu thuẫn về khái niệm: Multi-AZ là cơ chế TRONG một Region (trải qua các AZ), không có "cross-region Multi-AZ". Và quan trọng hơn: bản standby của Multi-AZ KHÔNG phục vụ truy vấn nào — nó chỉ nằm chờ để tiếp quản khi primary hỏng.
- C. Tạo snapshot rồi dựng CSDL mới từ snapshot ở Region kia — dữ liệu TĨNH tại thời điểm chụp: nó không tự cập nhật, nên báo cáo sẽ dùng dữ liệu cũ dần. Muốn mới thì phải chụp và khôi phục lại định kỳ — tốn kém và phức tạp.
- D. Read replica ở AZ khác, ứng dụng báo cáo kết nối qua VPN — giải quyết được vế "không ảnh hưởng primary" nhưng trượt vế hiệu năng: replica vẫn ở Region cũ, nên ứng dụng báo cáo vẫn phải truy vấn xuyên lục địa qua VPN — độ trễ cao, và VPN còn thêm một chặng nữa.
Ghi nhớ
Phân biệt hai tính năng của RDS — đây là một trong những câu hỏi kinh điển nhất: | | Multi-AZ | Read Replica | |---|---|---| | Mục đích | sẵn sàng cao / khôi phục sau sự cố | mở rộng đọc | | Nhân bản | đồng bộ | bất đồng bộ | | Standby/replica đọc được? | ❌ KHÔNG | ✅ CÓ | | Failover | tự động | thủ công (promote) | | Số lượng | 1 standby | tối đa 15 | | Xuyên Region | ❌ | ✅ |
Câu thần chú: Multi-AZ = tính sẵn sàng. Read replica = hiệu năng đọc.
Lợi ích kèm theo của cross-region read replica: | Lợi ích | Chi tiết | |---|---| | Giảm độ trễ đọc cho người dùng ở Region khác | ← câu này | | Khôi phục sau thảm hoạ | promote replica thành primary khi Region chính sập | | Cô lập tải phân tích | truy vấn nặng không chạm CSDL chính | | Di trú Region | promote rồi chuyển sang |
Ba lưu ý khi dùng cross-region read replica:
- Nhân bản là bất đồng bộ — có độ trễ, thường vài giây tới vài chục giây tuỳ khoảng cách và tải. Báo cáo chấp nhận được; giao dịch cần dữ liệu tức thì thì không.
- Chi phí truyền dữ liệu xuyên Region — đáng kể nếu lượng thay đổi lớn.
- Theo dõi
ReplicaLag— nếu nó tăng dần, replica đang không theo kịp.
Và với nhu cầu phân tích thật sự nặng, cân nhắc Amazon Redshift hoặc Athena trên dữ liệu đã export sang S3 — chúng được thiết kế cho truy vấn OLAP, còn read replica vẫn là CSDL giao dịch.
A company is building an application to track athlete performance using an Amazon DynamoDB table. Each item in the table is identified by a partition key (user_id) and a sort key (sport_name). The table design is shown below:
• Partition key: user_id
• Sort Key: sport_name
• Attributes: score, score_datetime
A Developer is asked to write a leaderboard application to display the top performers (user_id) based on the score for each sport_name.
What process will allow the Developer to extract results MOST efficiently from the DynamoDB table?
-
A
Create a local secondary index with a primary key of
sport_nameand a sort key ofscoreand get the results based on thescoreattribute -
B
Use a DynamoDB
scanoperation to retrieve scores anduser_idbased onsport_name, and order the results based on thescoreattribute -
C
Create a global secondary index with a partition key of
sport_nameand a sort key ofscore, and get the results -
D
Use a DynamoDB query operation with the key attributes of
user_idandsport_nameand order the results based on thescoreattribute
Xem giải thích
Đáp án
C — Tạo Global Secondary Index với partition key là sport_name và sort key là score.
Vì sao đúng
Bảng gốc có khoá chính là user_id (partition) + sport_name (sort). Cấu trúc đó trả lời tốt câu hỏi "vận động viên X có điểm ở những môn nào?", nhưng bảng xếp hạng cần câu hỏi ngược lại: "môn Y có ai điểm cao nhất?".
Với khoá hiện tại, muốn trả lời câu đó phải quét toàn bộ bảng — vì sport_name là sort key, và không thể truy vấn theo sort key mà không nêu partition key.
GSI đảo ngược cấu trúc khoá để phục vụ đúng mẫu truy vấn mới:
Bảng gốc: user_id (PK) + sport_name (SK)
GSI: sport_name (PK) + score (SK) ← đảo lại
Từ đó bảng xếp hạng chỉ là một Query:
table.query(
IndexName='BangXepHang',
KeyConditionExpression=Key('sport_name').eq('Bơi lội'),
ScanIndexForward=False, # điểm cao nhất trước
Limit=10 # top 10
)
ScanIndexForward=False cho thứ tự giảm dần — DynamoDB tự sắp xếp theo sort key, nên bảng xếp hạng gần như miễn phí về mặt tính toán.
Vì sao các phương án khác sai
- A. Tạo Local Secondary Index với primary key
sport_namevà sort keyscore— không thực hiện được: LSI bắt buộc dùng CÙNG partition key với bảng gốc (user_id), chỉ được đổi sort key. Không có cách nào tạo LSI với partition key khác. Đây là điểm loại tuyệt đối, và cũng là khác biệt quan trọng nhất giữa LSI và GSI. - B. Dùng
Scanđể lấy điểm theosport_namerồi sắp xếp — cho ra đáp án đúng nhưng cực kỳ kém hiệu quả: đọc toàn bộ bảng ở mỗi lần hiển thị bảng xếp hạng, tốn RCU tỷ lệ với kích thước bảng và chậm dần theo thời gian. Đề hỏi cách "MOST efficiently". - D. Dùng
Queryvớiuser_idvàsport_namerồi sắp xếp theoscore— sai mẫu truy vấn:Querybắt buộc nêu partition key, tức làuser_id. Nhưng bảng xếp hạng cần mọi vận động viên của một môn, không phải một vận động viên cụ thể.
Ghi nhớ
Khác biệt cốt lõi giữa hai loại index: | | LSI | GSI | |---|---|---| | Partition key | PHẢI giống bảng gốc | tự do chọn | | Sort key | bắt buộc, khác bảng gốc | tuỳ chọn | | Tạo lúc nào | CHỈ khi tạo bảng | bất cứ lúc nào | | Xoá được | ❌ | ✅ | | Số lượng | 5 | 20 | | Strongly consistent read | ✅ | ❌ không bao giờ | | Capacity | dùng chung với bảng | RIÊNG | | Giới hạn kích thước | 10 GB mỗi partition key | không |
Cách chọn rất gọn:
- Đổi partition key ⇒ bắt buộc GSI
- Giữ partition key, chỉ đổi cách sắp xếp ⇒ LSI được (nhưng phải nghĩ tới từ lúc tạo bảng)
Ba lưu ý khi dùng GSI:
- Cấp WCU riêng cho GSI — thiếu sẽ throttle cả bảng gốc, dù bảng gốc còn dư capacity. DynamoDB làm vậy để index không lệch dữ liệu.
- GSI luôn eventually consistent — bảng xếp hạng có thể trễ vài trăm mili giây, hoàn toàn chấp nhận được với nghiệp vụ này.
- Chiếu (project) hợp lý: dùng
KEYS_ONLYhoặcINCLUDEđể GSI nhỏ và rẻ hơn — chiếuALLlà nhân đôi chi phí lưu trữ.
Với bảng xếp hạng chỉ cần hiển thị tên và điểm, INCLUDE là lựa chọn tốt:
"Projection": {"ProjectionType": "INCLUDE", "NonKeyAttributes": ["user_id", "score_datetime"]}
An application will generate thumbnails from objects uploaded to an Amazon S3 bucket. The Developer has created the bucket configuration and the AWS Lambda function and has formulated the following AWS CLI command:
aws lambda add-permission --function-name CreateThumbnail --principal s3.amazonaws.com --statement-id s3invoke --action "lambda:InvokeFunction" --source-arn arn:aws:s3:::digitalcloudbucket-source --source-account 523107438921
What will be achieved by running the AWS CLI command?
-
A
A Lambda function will be created called CreateThumbnail with an Amazon SNS event source mapping that executes the function when objects are uploaded
-
B
The Lambda function
CreateThumbnailwill be granted permissions to access the objects in thedigitalcloudbucket-sourcebucket -
C
The Amazon S3 service principal (s3.amazonaws.com) will be granted permissions to perform the create an event-source mapping with the
digitalcloudbucket-sourcebucket -
D
The Amazon S3 service principal (s3.amazonaws.com) will be granted permissions to perform the
lambda:InvokeFunctionaction
Xem giải thích
Đáp án
D — Service principal của S3 (s3.amazonaws.com) được cấp quyền thực hiện hành động lambda:InvokeFunction.
Vì sao đúng
Đọc từng tham số của lệnh:
aws lambda add-permission \
--function-name CreateThumbnail \ ← thêm quyền VÀO hàm này
--principal s3.amazonaws.com \ ← CHO service principal của S3
--action "lambda:InvokeFunction" \ ← ĐƯỢC PHÉP gọi hàm
--source-arn arn:aws:s3:::digitalcloudbucket-source \ ← chỉ từ bucket này
--source-account 523107438921 ← thuộc tài khoản này
add-permission sửa resource-based policy của hàm Lambda — nó trả lời câu hỏi "ai được phép gọi tôi?":
{
"Sid": "s3invoke",
"Effect": "Allow",
"Principal": {"Service": "s3.amazonaws.com"},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:...:function:CreateThumbnail",
"Condition": {
"ArnLike": {"AWS:SourceArn": "arn:aws:s3:::digitalcloudbucket-source"},
"StringEquals": {"AWS:SourceAccount": "523107438921"}
}
}
Hai tham số cuối là điều kiện thu hẹp — chúng đảm bảo chỉ đúng bucket đó, trong đúng tài khoản đó mới gọi được hàm. Đây là biện pháp chống confused deputy: không có chúng, bất kỳ bucket S3 nào của bất kỳ ai cũng gọi được hàm của bạn.
Và lệnh này là bước bắt buộc khi cấu hình S3 event notification gọi Lambda — thiếu nó thì S3 báo lỗi ngay lúc lưu cấu hình notification.
Vì sao các phương án khác sai
- B. Hàm CreateThumbnail được cấp quyền truy cập object trong bucket — đảo ngược chiều: lệnh này cho S3 quyền gọi Lambda, không phải cho Lambda quyền đọc S3. Quyền chiều kia nằm ở execution role của hàm, cấp bằng IAM policy hoàn toàn khác.
- C. S3 service principal được cấp quyền tạo event-source mapping — nhầm khái niệm: event source mapping là cơ chế của các nguồn POLL-BASED (SQS, Kinesis, DynamoDB Streams). S3 không dùng event source mapping — nó đẩy sự kiện trực tiếp bằng
InvokeFunction. - A. Lệnh này tạo hàm Lambda với SNS event source mapping —
add-permissionkhông tạo hàm nào, và trong lệnh không hề có SNS.
Ghi nhớ
Hai chiều quyền cần phân biệt rõ — đây là điểm gây nhầm nhiều nhất: | Chiều | Cơ chế | Trả lời câu hỏi | |---|---|---| | Ai được gọi Lambda | resource-based policy (add-permission) | "ai được phép gọi tôi?" | | Lambda được làm gì | execution role (IAM policy) | "tôi được phép làm gì?" |
Với ứng dụng tạo thumbnail, bạn cần cả hai:
# Chiều 1: cho S3 gọi được hàm
aws lambda add-permission --function-name CreateThumbnail \
--principal s3.amazonaws.com --action lambda:InvokeFunction \
--statement-id s3invoke --source-arn arn:aws:s3:::kho-nguon
# Chiều 2: cho hàm đọc/ghi S3 — nằm trong execution role
{"Effect":"Allow","Action":["s3:GetObject","s3:PutObject"],
"Resource":["arn:aws:s3:::kho-nguon/*","arn:aws:s3:::kho-thumbnail/*"]}
Các service principal thường gặp: | Dịch vụ | Principal | |---|---| | S3 | s3.amazonaws.com | | SNS | sns.amazonaws.com | | EventBridge | events.amazonaws.com | | API Gateway | apigateway.amazonaws.com | | CloudWatch Logs | logs.amazonaws.com |
Ba cơ chế gọi Lambda — nhớ để không nhầm với event source mapping: | Cơ chế | Nguồn | Cần add-permission? | |---|---|---| | Push bất đồng bộ | S3, SNS, EventBridge | ✅ | | Push đồng bộ | API Gateway, ALB | ✅ | | Poll-based (event source mapping) | SQS, Kinesis, DynamoDB Streams | ❌ — dùng execution role |
Dòng cuối đáng nhớ: với nguồn poll-based, dịch vụ Lambda chủ động đọc, nên quyền nằm ở execution role (sqs:ReceiveMessage, kinesis:GetRecords), không phải resource-based policy.
Và lưu ý về --source-account: nó đặc biệt quan trọng với S3 vì tên bucket là toàn cầu — không có nó, ai đó tạo bucket trùng tên ở tài khoản khác vẫn có thể gọi hàm của bạn.
A Developer is creating an application that will utilize an Amazon DynamoDB table for storing session data. The data being stored is expected to be around 4.5KB in size and the application will make 20 eventually consistent reads/sec, and 12 standard writes/sec.
How many RCUs/WCUs are required?
-
A
40 RCU and 60 WCU
-
B
20 RCU and 60 WCU
-
C
10 RCU and 24 WCU
-
D
40 RCU and 12 WCU
Xem giải thích
Đáp án
B — 20 RCU và 60 WCU.
Vì sao đúng
Hai phép tính riêng biệt, với đơn vị khác nhau — đây là chỗ hay sai nhất.
RCU — đơn vị 4 KB:
Bước 1: làm tròn lên → ceil(4.5 / 4) = 2 đơn vị
Bước 2: eventually consistent → × 0,5 = 1 RCU mỗi lần đọc
Bước 3: nhân số lần → 1 × 20 = 20 RCU
WCU — đơn vị 1 KB:
Bước 1: làm tròn lên → ceil(4.5 / 1) = 5 đơn vị
Bước 2: ghi thường → × 1 = 5 WCU mỗi lần ghi
Bước 3: nhân số lần → 5 × 12 = 60 WCU
Kết quả: 20 RCU và 60 WCU.
Điểm đáng chú ý trong bài này: cùng một item 4,5 KB tốn 2 đơn vị đọc nhưng 5 đơn vị ghi — vì RCU dùng đơn vị 4 KB còn WCU dùng đơn vị 1 KB. Ghi luôn đắt hơn đọc rất nhiều.
Và chi tiết "4,5 KB" là cố ý: nó lố qua ngưỡng 4 KB một chút, nên tốn 2 đơn vị đọc thay vì 1 — minh hoạ tầm quan trọng của việc làm tròn lên.
Vì sao các phương án khác sai
- D. 40 RCU và 12 WCU — RCU tính như strongly consistent (không chia đôi), và WCU thì bỏ qua kích thước item (chỉ lấy 12 lần ghi).
- A. 40 RCU và 60 WCU — WCU đúng, nhưng RCU tính như strongly consistent.
- C. 10 RCU và 24 WCU — cả hai đều sai; có vẻ dùng nhầm đơn vị ở cả hai vế.
Ghi nhớ
Hai công thức cần thuộc, và chúng không đối xứng:
RCU — đơn vị 4 KB:
Strongly consistent : ceil(size / 4 KB) × số_lần_đọc
Eventually consistent: ceil(size / 4 KB) ÷ 2 × số_lần_đọc
Transactional : ceil(size / 4 KB) × 2 × số_lần_đọc
WCU — đơn vị 1 KB:
Ghi thường : ceil(size / 1 KB) × số_lần_ghi
Transactional : ceil(size / 1 KB) × 2 × số_lần_ghi
Ba lỗi phổ biến nhất:
- Nhầm đơn vị — RCU dùng 4 KB, WCU dùng 1 KB. Lỗi số một.
- Quên làm tròn LÊN — 4,5 KB tốn như 8 KB khi đọc và như 5 KB khi ghi.
- Bỏ qua từ khoá "strongly", "eventually", "transactional".
Bảng đối chiếu cho item 4,5 KB để nắm chắc: | Thao tác | Đơn vị | Mỗi lần | Kết quả | |---|---|---|---| | Đọc eventually | ceil(4.5/4) = 2 | 1 RCU | × 20 = 20 | | Đọc strongly | 2 | 2 RCU | × 20 = 40 | | Đọc transactional | 2 | 4 RCU | × 20 = 80 | | Ghi thường | ceil(4.5/1) = 5 | 5 WCU | × 12 = 60 | | Ghi transactional | 5 | 10 WCU | × 12 = 120 |
Một quan sát thiết kế đáng nhớ: vì WCU đắt hơn RCU khoảng 5 lần cho cùng kích thước item, việc giảm kích thước item hoặc giảm tần suất ghi thường tiết kiệm nhiều hơn hẳn so với tối ưu đường đọc.
Và với dữ liệu session như đề mô tả, hai tối ưu đáng cân nhắc: bật TTL để dọn tự động (miễn phí), và giữ item dưới 4 KB nếu có thể — chỉ cần bớt 0,5 KB là chi phí đọc giảm một nửa.
An application will ingest data at a very high throughput from several sources and stored in an Amazon S3 bucket for subsequent analysis. Which AWS service should a Developer choose for this requirement?
-
A
Amazon S3 Transfer Acceleration
-
B
Amazon Simple Queue Service (SQS)
-
C
Amazon Kinesis Data Analytics
-
D
Amazon Kinesis Data Firehose
Xem giải thích
Đáp án
D — Amazon Kinesis Data Firehose.
Vì sao đúng
Đề nêu ba yêu cầu, và Firehose khớp cả ba:
- Nạp dữ liệu thông lượng rất cao từ nhiều nguồn
- Lưu vào S3
- Để phân tích về sau
Firehose là dịch vụ nạp dữ liệu luồng vào đích lưu trữ — nó được thiết kế đúng cho việc này:
Nhiều nguồn → Kinesis Data Firehose → tự động gom lô, nén, mã hoá → S3
| Đặc điểm | Chi tiết |
|---|---|
| Hoàn toàn được quản lý | không có shard nào để tính và điều chỉnh |
| Tự co giãn | theo thông lượng thực tế |
| Gom lô tự động | theo kích thước hoặc thời gian (mặc định ~60 giây) |
| Nén và mã hoá | GZIP, Snappy, ZIP; mã hoá bằng KMS |
| Chuyển đổi định dạng | JSON → Parquet hoặc ORC — rất quan trọng cho phân tích |
| Biến đổi bằng Lambda | làm sạch dữ liệu trên đường đi |
Dòng "chuyển đổi định dạng" đáng chú ý với vế "subsequent analysis" trong đề: chuyển sang Parquet giúp truy vấn Athena sau này rẻ hơn 80–90% vì nó là định dạng cột có nén.
aws firehose create-delivery-stream \
--delivery-stream-name nap-du-lieu \
--s3-destination-configuration '{
"BucketARN": "arn:aws:s3:::kho-phan-tich",
"Prefix": "du-lieu/nam=!{timestamp:yyyy}/thang=!{timestamp:MM}/ngay=!{timestamp:dd}/",
"BufferingHints": {"SizeInMBs": 128, "IntervalInSeconds": 300},
"CompressionFormat": "GZIP"
}'
Phần Prefix với biến thời gian tạo sẵn cấu trúc phân vùng cho Athena — một tối ưu rất đáng làm ngay từ đầu.
Vì sao các phương án khác sai
- B. Amazon SQS — hàng đợi tin nhắn, không phải dịch vụ nạp dữ liệu vào kho lưu trữ. Bạn phải tự viết consumer đọc message rồi ghi vào S3, tự lo gom lô, nén, và xử lý lỗi. Ngoài ra SQS giới hạn 256 KB mỗi message.
- C. Amazon Kinesis Data Analytics — dịch vụ PHÂN TÍCH luồng đang chảy bằng SQL hoặc Apache Flink. Nó xử lý dữ liệu, không phải nạp và lưu trữ. Nó thường đứng sau một stream, không thay thế được vai trò nạp.
- A. S3 Transfer Acceleration — tối ưu tốc độ TẢI LÊN từ xa cho từng tệp riêng lẻ. Nó không phải dịch vụ nạp dữ liệu luồng, và không gom lô hay biến đổi gì.
Ghi nhớ
So sánh hai dịch vụ Kinesis hay bị lẫn: | | Data Firehose | Data Streams | |---|---|---| | Mục đích | NẠP vào đích lưu trữ | luồng thô cho nhiều consumer | | Quản lý shard | ❌ không có | ✅ phải tính và điều chỉnh | | Độ trễ | ~60 giây (gom lô) | dưới giây | | Phát lại | ❌ | ✅ tới 365 ngày | | Nhiều consumer độc lập | ❌ | ✅ | | Tính tiền | theo lượng dữ liệu nạp | theo shard-giờ |
Cách chọn: | Nhu cầu | Chọn | |---|---| | Chỉ nạp vào S3/Redshift/OpenSearch, gần thời gian thực | Firehose | | Dưới giây, nhiều consumer, phát lại được | Data Streams | | Phân tích liên tục trên luồng | Data Analytics / Managed Flink | | Phân tích dữ liệu đã lưu | Athena |
Các đích mà Firehose hỗ trợ: | Đích | Ghi chú | |---|---| | Amazon S3 | phổ biến nhất | | Amazon Redshift | qua S3 rồi COPY | | Amazon OpenSearch | tìm kiếm và trực quan hoá | | Splunk, Datadog, New Relic, MongoDB | HTTP endpoint |
Và một mẫu kiến trúc rất phổ biến kết hợp cả hai:
Nguồn → Data Streams → ┬→ Firehose → S3 (lưu trữ, phân tích bằng Athena)
└→ Lambda → xử lý thời gian thực
Cách này cho cả hai: độ trễ thấp cho xử lý tức thì, và lưu trữ giá rẻ cho phân tích về sau.
A Developer is creating an AWS Lambda function that will process medical images. The function is dependent on several libraries that are not available in the Lambda runtime environment. Which strategy should be used to create the Lambda deployment package?
-
A
Create a ZIP file with the source code and a
buildspec.yamlfile that installs the dependent libraries on AWS Lambda -
B
Create a ZIP file with the source code and a script that installs the dependent libraries at runtime
-
C
Create a ZIP file with the source code. Stage the dependent libraries on an Amazon S3 bucket indicated by the Lambda environment variable
LIBRARY_PATH -
D
Create a ZIP file with the source code and all dependent libraries
Xem giải thích
Đáp án
D — Tạo tệp ZIP chứa mã nguồn và toàn bộ thư viện phụ thuộc.
Vì sao đúng
Môi trường thực thi Lambda chỉ có sẵn thư viện chuẩn của runtime (cộng với AWS SDK ở Python và Node.js). Thư viện xử lý ảnh y tế như Pillow, OpenCV, pydicom, SimpleITK đều không có sẵn — nên phải đóng gói cùng mã.
Cấu trúc gói cho Python:
goi-trien-khai.zip
├── ham.py ← mã nguồn
├── PIL/ ← thư viện
├── pydicom/
├── numpy/
└── ...
Cách dựng:
pip install -r requirements.txt -t ./goi/
cp ham.py ./goi/
cd goi && zip -r ../goi-trien-khai.zip .
aws lambda update-function-code --function-name xu-ly-anh-y-te \
--zip-file fileb://goi-trien-khai.zip
Điểm cực kỳ quan trọng với thư viện xử lý ảnh: nhiều thư viện có phần mở rộng biên dịch sẵn theo hệ điều hành (.so). Cài trên macOS hay Windows rồi đóng gói sẽ lỗi khi chạy trên Lambda (vốn là Amazon Linux). Phải dựng gói trong môi trường tương thích:
docker run --rm -v "$PWD":/var/task public.ecr.aws/sam/build-python3.12 \
pip install -r requirements.txt -t ./goi/
Đây là lỗi phổ biến nhất khi đóng gói Lambda có thư viện xử lý ảnh.
Vì sao các phương án khác sai
- B. ZIP chứa mã nguồn và một script cài thư viện lúc chạy — sai vì nhiều lý do:
/var/taskchỉ đọc, thư mục ghi được duy nhất là/tmp; hàm có thể không có kết nối Internet (nhất là khi gắn vào VPC không có NAT); và việc cài đặt sẽ chạy lại ở mọi cold start, làm độ trễ tăng vọt. - C. ZIP chứa mã nguồn, thư viện đặt trên S3 và chỉ định bằng biến môi trường
LIBRARY_PATH— không có cơ chế nào như vậy: Lambda không tự tải thư viện từ S3. Bạn phải tự viết mã tải và giải nén vào/tmp— quay về vấn đề của phương án B. - A. ZIP chứa mã nguồn và tệp
buildspec.yamlđể cài thư viện trên Lambda — nhầm công cụ:buildspec.yamllà tệp của CodeBuild, chạy trong lúc build, không phải trong môi trường Lambda. CodeBuild có thể dùng nó để dựng gói, nhưng gói kết quả vẫn phải chứa sẵn thư viện.
Ghi nhớ
Ba cách đưa thư viện vào Lambda: | Cách | Giới hạn | Dùng khi | |---|---|---| | ZIP kèm thư viện | 50 MB nén / 250 MB giải nén | mặc định | | Lambda Layer | 5 layer, tổng vẫn 250 MB | dùng chung cho nhiều hàm | | Container image | 10 GB | thư viện rất nặng (OpenCV, mô hình ML) |
Với ảnh y tế, dòng cuối rất đáng cân nhắc: OpenCV đầy đủ, SimpleITK, hoặc mô hình học máy dễ dàng vượt 250 MB. Khi đó container image là lối thoát duy nhất:
FROM public.ecr.aws/lambda/python:3.12
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY ham.py ${LAMBDA_TASK_ROOT}
CMD ["ham.lambda_handler"]
Và nếu thư viện dùng chung cho nhiều hàm, Layer là lựa chọn tốt: tách thư viện khỏi mã, nên mỗi lần sửa mã chỉ tải lên vài KB thay vì vài chục MB.
Các giới hạn khác cần thuộc: | Giới hạn | Giá trị | |---|---| | Gói tải trực tiếp | 50 MB (nén) | | Gói qua S3 | 250 MB (giải nén) | | Container image | 10 GB | | /tmp | 512 MB – 10 GB | | Bộ nhớ | 128 MB – 10.240 MB | | Timeout | 15 phút |
Với xử lý ảnh y tế (tệp DICOM thường lớn), nhớ tăng /tmp và tăng bộ nhớ — CPU của Lambda tỷ lệ với bộ nhớ, nên tăng RAM thường làm hàm chạy nhanh hơn và tổng chi phí có thể giảm.
A Developer wants the ability to roll back to a previous version of an AWS Lambda function in the event of errors caused by a new deployment.
How can the Developer achieve this with MINIMAL impact on users?
-
A
Change the application to use a version ARN that points to the latest published version. Deploy the new version of the code. Update the application to point to the ARN of the new version of the code. If too many errors are encountered, point the application back to the ARN of the previous version
-
B
Change the application to use the $LATEST version. Update and save code. If too many errors are encountered, modify and save the code
-
C
Change the application to use an alias that points to the current version. Deploy the new version of the code. Update the alias to direct 10% of users to the newly deployed version. If too many errors are encountered, send 100% of traffic to the previous version
-
D
Change the application to use an alias that points to the current version. Deploy the new version of the code. Update the alias to use the newly deployed version. If too many errors are encountered, point the alias back to the previous version
Xem giải thích
Đáp án
D — Dùng alias trỏ tới version hiện tại, triển khai version mới, cập nhật alias sang version mới; nếu lỗi thì trỏ alias về version cũ.
Vì sao đúng
Đề nêu hai yêu cầu: rollback về version trước khi có lỗi, với tác động tối thiểu tới người dùng.
Alias là con trỏ có tên, cập nhật được — và đó là cơ chế rollback nhanh nhất của Lambda:
# Triển khai version mới
version=$(aws lambda publish-version --function-name xu-ly --query Version --output text)
aws lambda update-alias --function-name xu-ly --name prod --function-version $version
# Có vấn đề → rollback TỨC THÌ
aws lambda update-alias --function-name xu-ly --name prod --function-version 4
Vì sao "tác động tối thiểu": rollback chỉ là một lời gọi API, có hiệu lực trong vài giây. Version cũ vẫn nguyên vẹn ở đó — không phải triển khai lại gì, không phải build lại.
Và điểm kiến trúc quan trọng: mọi thứ gọi hàm đều trỏ vào alias, không trỏ vào version. Nên API Gateway, event source, và quyền không cần đụng tới khi bạn chuyển version:
API Gateway → alias "prod" → version 5
↓ (rollback)
alias "prod" → version 4
API Gateway KHÔNG ĐỔI GÌ CẢ
Vì sao các phương án khác sai
- C. Dùng alias, triển khai version mới, rồi cho 10% người dùng sang version mới; nếu lỗi thì chuyển 100% về version cũ — đây là phương án gần nhất và đáng bàn kỹ. Nó mô tả canary deployment bằng weighted routing, và là cách làm rất tốt trong thực tế. Nhưng nó không phải điều đề hỏi: đề nói về khả năng rollback khi có lỗi, không nói về phát hành từng phần. Ngoài ra, cách này vẫn để 10% người dùng gặp lỗi — nhiều hơn phương án D nếu bạn phát hiện lỗi nhanh. (Nếu đề hỏi "cách an toàn nhất để phát hành", C mới là đáp án.)
- A. Dùng version ARN trỏ tới version mới nhất, cập nhật ứng dụng trỏ sang ARN mới — đòi sửa và triển khai lại ỨNG DỤNG ở mỗi lần phát hành, và rollback cũng vậy. Đó chính là vấn đề mà alias sinh ra để giải quyết.
- B. Dùng
$LATEST, sửa và lưu mã; nếu lỗi thì sửa lại — tệ nhất:$LATESTthay đổi ngay khi bạn cập nhật mã, nên không có phiên bản nào để quay về. Rollback nghĩa là sửa mã ngược lại bằng tay — chậm, dễ sai, và không có bản ghi nào về việc gì đã đổi.
Ghi nhớ
| Khái niệm | Là gì | Đổi được? |
|---|---|---|
$LATEST |
bản đang sửa | ✅ (đừng dùng cho production) |
| Version | bản chụp BẤT BIẾN của mã + cấu hình | ❌ |
| Alias | con trỏ có tên tới một hoặc HAI version | ✅ |
Mẫu thực hành tốt:
$LATEST ← nơi phát triển
version 1, 2, 3, 4, 5 ← bất biến
alias "dev" → $LATEST
alias "test" → version 5
alias "prod" → version 4
Alias còn hỗ trợ weighted routing cho canary — kết hợp cả hai ý tưởng:
aws lambda update-alias --function-name xu-ly --name prod \
--function-version 5 --routing-config '{"AdditionalVersionWeights": {"4": 0.9}}'
# 10% sang version 5, 90% ở lại version 4
Ba lưu ý quan trọng khi dùng alias:
- Cấp quyền cho từng alias, không cấp chung chung — thiếu qualifier là API Gateway trả 500 không nói gì:
aws lambda add-permission --function-name xu-ly --qualifier prod \ --statement-id ApiGatewayInvoke --action lambda:InvokeFunction \ --principal apigateway.amazonaws.com - Chỉ chia traffic được giữa ĐÚNG HAI version — không phải ba trở lên, và không dùng được với
$LATEST. - Provisioned concurrency chỉ đặt được trên alias hoặc version — nên muốn loại bỏ cold start cho production thì buộc phải dùng alias.
Và với tự động hoá đầy đủ, CodeDeploy với DeploymentPreference làm sẵn cả canary lẫn tự rollback khi CloudWatch alarm kêu — không phải ngồi canh.
A Development team wants to instrument their code to provide more detailed information to AWS X-Ray than simple outgoing and incoming requests. This will generate large amounts of data, so the Development team wants to implement indexing so they can filter the data.
What should the Development team do to achieve this?
-
A
Add metadata to the segment document
-
B
Add annotations to the segment document
-
C
Install required plugins for the appropriate AWS SDK
-
D
Configure the necessary X-Ray environment variables
Xem giải thích
Đáp án
B — Thêm annotation vào segment document.
Vì sao đúng
X-Ray cho phép gắn hai loại dữ liệu vào segment, và chỉ một loại được đánh chỉ mục:
| Loại | Đánh chỉ mục | Lọc được bằng filter expression |
|---|---|---|
| Annotation | ✅ | ✅ |
| Metadata | ❌ | ❌ |
Đề nói rõ cần "implement indexing so they can filter the data" — nên bắt buộc phải dùng annotation:
from aws_xray_sdk.core import xray_recorder
@xray_recorder.capture('xu_ly_don_hang')
def xu_ly(don_hang):
xray_recorder.put_annotation('don_hang_id', don_hang['id'])
xray_recorder.put_annotation('loai_khach', 'vip')
xray_recorder.put_annotation('tong_tien', don_hang['tong'])
xray_recorder.put_metadata('chi_tiet', don_hang) # để đọc, không lọc được
...
Rồi lọc bằng filter expression:
annotation.don_hang_id = "DH-12345"
annotation.loai_khach = "vip" AND responsetime > 3
annotation.tong_tien > 1000000
Với ứng dụng sinh lượng trace rất lớn như đề mô tả, khả năng lọc này là thứ biến đống dữ liệu thành công cụ chẩn đoán dùng được.
Vì sao các phương án khác sai
- A. Thêm metadata vào segment document — đây là bẫy chính, và khác biệt cần thuộc: metadata KHÔNG được đánh chỉ mục, nên không lọc được. Nó vẫn hữu ích — chứa được cấu trúc JSON phức tạp và không giới hạn số lượng — nhưng chỉ để đọc khi đã mở trace ra.
- C. Cài plugin cho AWS SDK — plugin của X-Ray (EC2, ECS, Elastic Beanstalk plugin) bổ sung thông tin về môi trường chạy vào segment (instance ID, container ID). Chúng không tạo ra khả năng lọc theo dữ liệu nghiệp vụ.
- D. Cấu hình biến môi trường của X-Ray — các biến như
AWS_XRAY_DAEMON_ADDRESS,AWS_XRAY_CONTEXT_MISSINGđiều chỉnh cách SDK hoạt động, không thêm dữ liệu vào segment.
Ghi nhớ
So sánh hai loại dữ liệu — đây là quyết định thiết kế quan trọng nhất khi dùng X-Ray: | | Annotation | Metadata | |---|---|---| | Tìm kiếm được | ✅ | ❌ | | Số lượng tối đa | 50 mỗi trace | không giới hạn | | Kiểu dữ liệu | chuỗi, số, boolean | bất kỳ JSON nào | | Dùng cho | user_id, order_id, environment, tenant | payload đầy đủ, chi tiết để đọc |
Nguyên tắc: thứ gì cần TÌM thì là annotation, thứ gì chỉ để ĐỌC thì là metadata.
Ba trường tích hợp sẵn cũng lọc được, với cú pháp riêng (không có tiền tố annotation.):
user("nguyenvana")
service("api-don-hang") { fault = true }
http.status = 500
responsetime > 5
API để tìm kiếm trace là GetTraceSummaries:
aws xray get-trace-summaries \
--start-time 2026-08-05T00:00:00 --end-time 2026-08-05T23:59:59 \
--filter-expression 'annotation.loai_khach = "vip" AND responsetime > 3'
Rồi BatchGetTraces lấy chi tiết đầy đủ theo trace ID trả về.
Và với ứng dụng sinh nhiều trace, sampling rule là công cụ đi kèm quan trọng — nó cho phép ghi đầy đủ những request bạn quan tâm trong khi lấy mẫu thưa phần còn lại:
{
"rule_name": "don-hang-vip",
"priority": 100,
"fixed_target": 10,
"rate": 1.0,
"service_name": "api-don-hang",
"url_path": "/don-hang/vip/*"
}
Mặc định X-Ray chỉ lấy 1 request mỗi giây cộng 5% số còn lại — nên nếu không khai rule riêng, những request hiếm mà quan trọng rất dễ không được ghi lại.