Ngân hàng đề — AWS Certified Developer Associate
Tìm thấy 1356 câu.
A developer has pushed a Lambda function that pushes data into an RDS MySQL database with the following Python code:
def handler(event, context):
mysql = mysqlclient.connect()
data = event['data']
mysql.execute(f"INSERT INTO foo (bar) VALUES (${data});")
mysql.close()
return
On the first execution, the Lambda function takes 2 seconds to execute. On the second execution and all the subsequent ones, the Lambda function takes 1.9 seconds to execute.
What can be done to improve the execution time of the Lambda function?
-
A
Increase the Lambda function RAM
-
B
Upgrade the MySQL instance type
-
C
Move the database connection out of the handler
-
D
Change the runtime to Node.js
Xem giải thích
Đáp án
C — Đưa phần kết nối CSDL ra ngoài handler.
Vì sao đúng
Manh mối trong đề rất rõ ràng: lần chạy đầu 2 giây, các lần sau 1,9 giây — gần như không cải thiện gì.
Nếu chỉ là cold start, lần chạy thứ hai đã phải nhanh hơn hẳn. Việc thời gian gần như không đổi chứng tỏ có một việc tốn thời gian đang lặp lại ở mỗi lần gọi — và nhìn vào mã thì thấy ngay:
def handler(event, context):
mysql = mysqlclient.connect() # ← MỞ KẾT NỐI MỚI Ở MỖI LẦN GỌI
...
mysql.close() # ← rồi đóng lại
Mở một kết nối MySQL tốn hàng trăm mili giây: bắt tay TCP, xác thực, thương lượng SSL. Làm lại việc đó ở mỗi lần gọi là lãng phí toàn bộ cơ chế tái sử dụng execution context của Lambda.
Cách sửa — đưa kết nối vào vùng init, chạy một lần mỗi môi trường:
import mysqlclient
mysql = mysqlclient.connect() # ← NGOÀI handler: chạy MỘT LẦN
def handler(event, context):
data = event['data']
mysql.execute("INSERT INTO foo (bar) VALUES (%s)", (data,))
return
Sau khi sửa: lần đầu vẫn ~2 giây (cold start + kết nối), nhưng các lần sau chỉ còn vài chục mili giây.
(Ghi chú thêm: mã trong đề còn có lỗ hổng SQL injection vì nội suy chuỗi trực tiếp vào câu SQL — nên dùng tham số hoá như ở trên.)
Vì sao các phương án khác sai
- A. Tăng RAM cho hàm — tăng RAM cũng tăng CPU, nên hàm CPU-bound sẽ nhanh hơn. Nhưng ở đây thời gian chủ yếu là chờ mạng khi mở kết nối — thêm CPU không rút ngắn được.
- B. Nâng cấp instance type của MySQL — CSDL không phải nút thắt; một lệnh
INSERTđơn giản không cần máy mạnh hơn. Nút thắt là việc mở kết nối, lặp lại mỗi lần. - D. Đổi runtime sang Node.js — đổi ngôn ngữ không sửa được lỗi thiết kế. Mã Node.js viết theo cùng kiểu (mở kết nối trong handler) sẽ chậm y hệt.
Ghi nhớ
Cấu trúc một hàm Lambda được tối ưu:
# ── Vùng INIT: chạy MỘT LẦN mỗi execution context ──
import boto3
db = ket_noi_csdl()
s3 = boto3.client('s3')
CAU_HINH = tai_cau_hinh()
def handler(event, context):
# ── Vùng INVOKE: chạy MỖI lần gọi ──
return xu_ly(event, db, s3, CAU_HINH)
Bốn thứ nên đặt trong vùng init: kết nối CSDL, SDK client, cấu hình và bí mật (kèm TTL), biểu thức chính quy đã biên dịch.
Và với Lambda + RDS, hãy dùng RDS Proxy: Lambda mở rộng rất nhanh và dễ làm cạn connection pool của CSDL; Proxy gộp và tái sử dụng kết nối, giải quyết đúng vấn đề đó ở quy mô lớn.
A company has hosted its restaurant review website on an Amazon EC2 instance. The website supports multiple languages and the preferred language is added as a query string parameter to the request. The directory structure and file names for all versions of the website are identical. The website responds with the chosen language's webpage when accessed directly. However, when the same webpage is accessed through the configured CloudFront distribution, it defaults to a single language.
How will you fix this issue?
-
A
Create a new cache policy for the CloudFront distribution and set the cache behavior to
Query string forwarding and caching. In the Query string whitelist field include the language string. Update the CloudFront distribution to use the new cache policy -
B
Create a new cache policy for the CloudFront distribution and set the cache behavior to
Noneto improve caching performance. Update the CloudFront distribution to use the new cache policy -
C
Create a new cache policy for the CloudFront distribution and set the cache behavior to
Cache based on selected request headers. UseWhitelist Headersas the caching criteria -
D
Choose the
Customizeoption for theObject Cachingsetting and reduce theDefault TTLvalue so that CloudFront forwards requests to your origin more frequently
Xem giải thích
Đáp án
A — Tạo cache policy mới với hành vi chuyển tiếp và cache theo query string, đưa tham số ngôn ngữ vào whitelist.
Vì sao đúng
Triệu chứng: truy cập thẳng máy chủ thì đúng ngôn ngữ, nhưng qua CloudFront thì luôn ra một ngôn ngữ.
Nguyên nhân nằm ở cache key của CloudFront. Mặc định, CloudFront KHÔNG đưa query string vào cache key và không chuyển tiếp chúng tới origin:
Request 1: /trang-chu?lang=vi → CloudFront cache dưới khoá "/trang-chu"
→ gọi origin không kèm ?lang=vi
Request 2: /trang-chu?lang=en → cùng khoá "/trang-chu" → TRẢ VỀ BẢN CACHE (tiếng Việt)
Đưa lang vào query string whitelist sửa cả hai vế cùng lúc:
- CloudFront chuyển tiếp tham số tới origin, nên origin trả về đúng ngôn ngữ
- CloudFront đưa tham số vào cache key, nên mỗi ngôn ngữ có một mục cache riêng
/trang-chu?lang=vi → mục cache riêng
/trang-chu?lang=en → mục cache riêng
Vì sao whitelist chứ không phải "chuyển tiếp tất cả": mỗi tham số trong cache key nhân số mục cache lên. Tham số theo dõi quảng cáo (utm_source, fbclid…) sẽ tạo ra vô số bản sao giống hệt nhau, làm tỷ lệ trúng cache sụp đổ. Whitelist chỉ đúng tham số ảnh hưởng tới nội dung là cách tối ưu.
Vì sao các phương án khác sai
- B. Đặt cache behavior thành None — đi ngược lại: bỏ hẳn query string khỏi cache key nghĩa là giữ nguyên vấn đề, và origin cũng không nhận được tham số.
- C. Cache theo request header với whitelist header — sai cơ chế. Đề nói rõ ngôn ngữ được truyền bằng query string parameter, không phải header. (Nếu ứng dụng dùng header
Accept-Languagethì phương án này mới đúng.) - D. Giảm TTL mặc định — chỉ làm CloudFront hỏi origin thường xuyên hơn, nhưng vì query string vẫn không được chuyển tiếp, origin vẫn trả về cùng một ngôn ngữ. Nó cũng làm mất phần lớn lợi ích của CDN.
Ghi nhớ
Cache key của CloudFront được cấu thành từ: | Thành phần | Mặc định | |---|---| | Đường dẫn URL | luôn có | | Query string | không có — phải whitelist hoặc "all" | | Header | không có — phải whitelist | | Cookie | không có — phải whitelist |
Nguyên tắc thiết kế cache key:
Đưa vào cache key đúng những thứ làm THAY ĐỔI NỘI DUNG, không hơn.
Càng nhiều thành phần thì cache càng phân mảnh và tỷ lệ trúng càng thấp.
Và nhớ khái niệm mới: origin request policy (quyết định cái gì được chuyển tiếp tới origin) tách biệt với cache policy (quyết định cái gì vào cache key) — bạn có thể chuyển tiếp một header mà không đưa nó vào cache key.
A development team has a mix of applications hosted on-premises as well as on EC2 instances. The on-premises application controls all applications deployed on the EC2 instances. In case of any errors, the team wants to leverage Amazon CloudWatch to monitor and troubleshoot the on-premises application.
As a Developer Associate, which of the following solutions would you suggest to address this use-case?
-
A
Upload log files from the on-premises server to S3 and let CloudWatch process the files from S3
-
B
Configure the CloudWatch agent on the on-premises server by using IAM user credentials with permissions for CloudWatch
-
C
Configure CloudWatch Logs to directly read the logs from the on-premises server
-
D
Upload log files from the on-premises server to an EC2 instance which further forwards the logs to CloudWatch
Xem giải thích
Đáp án
B — Cấu hình CloudWatch agent trên máy chủ on-premises, dùng IAM user credentials có quyền CloudWatch.
Vì sao đúng
CloudWatch agent chạy được trên máy chủ ngoài AWS — đó là cách chính thức để đưa log và metric từ on-premises vào CloudWatch.
Khác biệt duy nhất so với chạy trên EC2 là cách cấp thông tin xác thực: máy on-premises không có instance profile, nên phải cấu hình riêng:
# Trên máy chủ on-premises
aws configure --profile AmazonCloudWatchAgent
# Nhập access key và secret key của IAM user có quyền CloudWatch
// /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json
{
"agent": {"credentials": {"profile": "AmazonCloudWatchAgent"}},
"logs": {"logs_collected": {"files": {"collect_list": [{
"file_path": "/var/log/ung-dung/*.log",
"log_group_name": "on-prem/ung-dung",
"log_stream_name": "{hostname}"
}]}}}
}
Quyền cần: CloudWatchAgentServerPolicy — cho phép PutLogEvents, PutMetricData, CreateLogGroup, CreateLogStream.
Kết quả: log của máy on-premises và log của EC2 nằm chung trong CloudWatch Logs, truy vấn được cùng lúc bằng Logs Insights — đúng nhu cầu giám sát và gỡ lỗi mà đề nêu.
Vì sao các phương án khác sai
- C. "Cấu hình CloudWatch Logs đọc thẳng log từ máy chủ on-premises" — không làm được. CloudWatch Logs là dịch vụ nhận dữ liệu được đẩy vào; nó không tự đi lấy log từ máy chủ nào cả. Luôn phải có agent hoặc lời gọi API từ phía nguồn.
- A. Tải log lên S3 rồi để CloudWatch xử lý — CloudWatch Logs không đọc từ S3. Chiều ngược lại thì có (export log từ CloudWatch ra S3), nhưng không có chiều này. Và cách này thêm độ trễ và thêm bước phải tự dựng.
- D. Đẩy log sang một EC2 rồi EC2 chuyển tiếp lên CloudWatch — thêm một máy trung gian hoàn toàn không cần thiết: agent trên chính máy on-premises gửi thẳng được. Máy trung gian còn thành điểm hỏng đơn lẻ.
Ghi nhớ
Cách cấp thông tin xác thực cho agent theo môi trường: | Môi trường | Cơ chế | |---|---| | EC2 | instance profile | | On-premises | IAM user credentials, hoặc tốt hơn: SSM hybrid activation |
SSM hybrid activation đáng nhắc riêng: nó cấp thông tin xác thực tạm thời tự xoay vòng cho máy ngoài AWS, thay vì access key tĩnh nằm trên đĩa. Đây là cách an toàn hơn hẳn và là khuyến nghị hiện hành của AWS cho môi trường lai.
Và nhớ ba metric không có sẵn trên EC2 lẫn on-premises, luôn cần agent: bộ nhớ, dung lượng đĩa còn trống, swap.
An IT company leverages CodePipeline to automate its release pipelines. The development team wants to write a Lambda function that will send notifications for state changes within the pipeline.
As a Developer Associate, which steps would you suggest to associate the Lambda function with the event source?
-
A
Set up an Amazon CloudWatch alarm that monitors status changes in Code Pipeline and triggers the Lambda function
-
B
Set up an Amazon CloudWatch Events rule that uses CodePipeline as an event source with the target as the Lambda function
-
C
Use the Lambda console to configure a trigger that invokes the Lambda function with CodePipeline as the event source
-
D
Use the CodePipeline console to set up a trigger for the Lambda function
Xem giải thích
Đáp án
B — Tạo CloudWatch Events (EventBridge) rule dùng CodePipeline làm event source, với target là hàm Lambda.
Vì sao đúng
CodePipeline không gọi Lambda trực tiếp để báo thay đổi trạng thái. Nó phát sự kiện lên EventBridge, và bạn tạo rule để định tuyến sự kiện đó tới bất kỳ target nào:
{
"source": ["aws.codepipeline"],
"detail-type": ["CodePipeline Pipeline Execution State Change",
"CodePipeline Stage Execution State Change",
"CodePipeline Action Execution State Change"],
"detail": {"state": ["FAILED", "SUCCEEDED"]}
}
Rule này gọi Lambda, và hàm nhận được đầy đủ ngữ cảnh: tên pipeline, stage, action, trạng thái, thời điểm.
Kiến trúc:
CodePipeline → phát sự kiện → EventBridge rule → Lambda → SNS / Slack / hệ nội bộ
EventBridge cũng cho lọc rất hẹp ngay ở tầng rule — chỉ pipeline nào, chỉ trạng thái nào — nên Lambda không bị gọi cho những sự kiện không quan tâm.
Vì sao các phương án khác sai
- C. "Dùng Lambda console tạo trigger với CodePipeline làm event source" — CodePipeline không phải event source hợp lệ của Lambda. Danh sách event source mapping của Lambda chỉ có SQS, Kinesis, DynamoDB Streams, MSK, Amazon MQ, DocumentDB. Với CodePipeline, đường đi bắt buộc qua EventBridge.
- D. "Dùng CodePipeline console để tạo trigger cho Lambda" — CodePipeline có Lambda invoke action (một stage gọi Lambda như một bước trong pipeline), nhưng đó là chuyện khác hẳn: nó chạy trong luồng pipeline, không phải phản ứng với thay đổi trạng thái. Và console CodePipeline không có mục "trigger cho thông báo".
- A. CloudWatch alarm giám sát thay đổi trạng thái — alarm chỉ làm việc với metric số. Thay đổi trạng thái pipeline là sự kiện, không phải metric — không có ngưỡng nào để đặt alarm.
Ghi nhớ
Ba detail-type của CodePipeline, từ rộng tới hẹp: | detail-type | Phạm vi | |---|---| | CodePipeline Pipeline Execution State Change | cả pipeline | | CodePipeline Stage Execution State Change | một stage | | CodePipeline Action Execution State Change | một action — có type.category để lọc |
Với đích là Slack hoặc Chime, có thể dùng AWS Chatbot làm target thay Lambda — nó lo sẵn phần định dạng payload, không phải viết mã.
Nguyên tắc chung: dịch vụ AWS phát sự kiện ⇒ EventBridge là lớp định tuyến phổ quát.
An IT company uses AWS CloudFormation templates to provision their AWS infrastructure for Amazon EC2, Amazon VPC, and Amazon S3 resources. Using cross-stack referencing, a developer creates a stack called NetworkStack which will export the subnetId that can be used when creating EC2 instances in another stack.
To use the exported value in another stack, which of the following functions must be used?
-
A
!Ref -
B
!GetAtt -
C
!Sub -
D
!ImportValue
Xem giải thích
Đáp án
D — !ImportValue (Fn::ImportValue).
Vì sao đúng
Chia sẻ giá trị giữa hai stack CloudFormation đi theo cặp Export → ImportValue:
NetworkStack — công bố:
Outputs:
SubnetId:
Value: !Ref SubnetChinh
Export:
Name: NetworkStack-SubnetId
Stack tiêu thụ — nhập vào:
Resources:
MayChu:
Type: AWS::EC2::Instance
Properties:
SubnetId: !ImportValue NetworkStack-SubnetId
Đề hỏi hàm dùng để sử dụng giá trị đã export ở stack khác — tức là phía tiêu thụ, nên đáp án là !ImportValue.
Kèm theo là một cơ chế bảo vệ đáng giá: CloudFormation không cho xoá hoặc sửa một export đang được stack khác import. Xoá nhầm subnet thì lệnh cập nhật thất bại ngay, thay vì âm thầm phá hỏng stack kia.
Vì sao các phương án khác sai
- A.
!Ref— trả về giá trị của một parameter hoặc tài nguyên trong CÙNG stack. Nó không nhìn thấy tài nguyên hay export của stack khác. - B.
!GetAtt— lấy thuộc tính của một tài nguyên trong cùng stack (!GetAtt MyBucket.Arn). Cũng chỉ hoạt động trong phạm vi một stack. - C.
!Sub— thay thế chuỗi, chèn biến vào một chuỗi mẫu (!Sub "arn:aws:s3:::${TenBucket}"). Nó không lấy giá trị từ stack khác — dù có thể kết hợp vớiImportValue:Value: !Sub - "${Subnet}-web" - Subnet: !ImportValue NetworkStack-SubnetId
Ghi nhớ
Các intrinsic function hay dùng và phạm vi của chúng: | Hàm | Lấy gì | Phạm vi | |---|---|---| | !Ref | giá trị parameter / ID tài nguyên | cùng stack | | !GetAtt | thuộc tính của tài nguyên | cùng stack | | !ImportValue | giá trị đã export | stack khác (cùng tài khoản + Region) | | !Sub | thay thế chuỗi | — | | !FindInMap | tra cứu trong Mappings | cùng stack |
Ba ràng buộc của cross-stack reference: tên export duy nhất trong một tài khoản + Region, không xuyên Region hay xuyên tài khoản, và không xoá được export đang bị import.
Cần chia sẻ xuyên Region thì dùng SSM Parameter Store thay cho export.
Your Lambda function must use the Node.js drivers to connect to your RDS PostgreSQL database in your VPC.
How do you bundle your Lambda function to add the dependencies?
-
A
Zip the function and the dependencies separately and upload them in AWS Lambda as two parts
-
B
Zip the function as-is with a package.json file so that AWS Lambda can resolve the dependencies for you
-
C
Put the function and the dependencies in one folder and zip them together
-
D
Upload the code through the AWS console and upload the dependencies as a zip
Xem giải thích
Đáp án
C — Đặt mã hàm và các phụ thuộc vào cùng một thư mục rồi nén chung.
Vì sao đúng
Lambda giải nén gói triển khai vào /var/task, và runtime tìm module theo cách chuẩn của ngôn ngữ đó. Với Node.js, đó là thư mục node_modules nằm cùng cấp với mã:
ham-lambda.zip
├── index.js ← mã hàm
├── package.json
└── node_modules/ ← PHỤ THUỘC, nén CÙNG
├── pg/
└── ...
Quy trình:
mkdir ham-lambda && cd ham-lambda
npm install pg # cài phụ thuộc vào node_modules/
# viết index.js
zip -r ../ham-lambda.zip . # nén TẤT CẢ cùng nhau
Điểm mấu chốt: Lambda không có bước cài đặt. Nó không chạy npm install, không đọc package.json để tải gói. Mọi thứ hàm cần phải có sẵn trong gói hoặc trong một layer.
Vì sao các phương án khác sai
- B. Nén hàm kèm
package.jsonđể Lambda tự giải quyết phụ thuộc — đây là hiểu nhầm phổ biến nhất. Lambda KHÔNG chạynpm install. Gói lên thiếunode_modulesthì hàm lỗi ngay:Cannot find module 'pg'. - A. Nén riêng rồi tải lên thành hai phần — Lambda chỉ nhận MỘT gói triển khai cho mỗi hàm. Không có khái niệm tải lên nhiều phần rồi ghép.
- D. Tải mã qua Console và tải phụ thuộc dưới dạng zip riêng — cùng vấn đề: một hàm chỉ có một gói. (Console cho phép sửa mã trực tiếp, nhưng chỉ khi gói dưới 3 MB và không có phụ thuộc.)
Ghi nhớ
Vị trí phụ thuộc theo ngôn ngữ, khi nén cùng gói: | Runtime | Vị trí | |---|---| | Node.js | node_modules/ ở gốc | | Python | thư mục gói ở gốc (pip install -t .) | | Java | lib/*.jar hoặc fat JAR | | .NET | tất cả DLL ở gốc |
Và giải pháp tốt hơn khi phụ thuộc dùng chung giữa nhiều hàm: Lambda Layer. Layer được giải nén vào /opt, và runtime tự tìm ở đó:
layer.zip
└── nodejs/node_modules/pg/ ← cấu trúc bắt buộc cho Node.js
Layer giúp gói hàm nhỏ gọn, deploy nhanh hơn, và cập nhật thư viện một chỗ cho nhiều hàm.
Your company is shifting towards Elastic Container Service (ECS) to deploy applications. The process should be automated using the AWS CLI to create a service where at least ten instances of a task definition are kept running under the default cluster.
Which of the following commands should be executed?
-
A
aws ecs run-task --cluster default --task-definition ecs-demo -
B
aws ecs create-service --service-name ecs-simple-service --task-definition ecs-demo --desired-count 10 -
C
docker-compose create ecs-simple-service -
D
aws ecr create-service --service-name ecs-simple-service --task-definition ecs-demo --desired-count 10
Xem giải thích
Đáp án
B — aws ecs create-service --service-name ecs-simple-service --task-definition ecs-demo --desired-count 10
Vì sao đúng
Yêu cầu: duy trì ít nhất 10 bản của một task definition luôn chạy. Từ khoá là "kept running" — tức là cần một cơ chế giám sát và tự phục hồi.
Đó chính là khác biệt giữa hai khái niệm cốt lõi của ECS:
run-task |
create-service |
|
|---|---|---|
| Vòng đời | chạy một lần rồi thôi | duy trì liên tục |
| Task chết | không được thay | ECS tự tạo task mới |
| Số lượng mong muốn | không có | --desired-count |
| Gắn load balancer | không | ✅ |
| Rolling update | không | ✅ |
| Hợp cho | job theo lô, tác vụ một lần | dịch vụ chạy dài |
ECS service scheduler liên tục so số task đang chạy với desired-count và bù ngay khi thiếu — đó là điều đề cần.
aws ecs create-service \
--cluster default \
--service-name ecs-simple-service \
--task-definition ecs-demo \
--desired-count 10
(Không khai --cluster thì ECS dùng cluster default, đúng như đề mô tả.)
Vì sao các phương án khác sai
- A.
aws ecs run-task— chạy task một lần. Task chết là không có gì tạo lại, và không có tham số nào để giữ 10 bản. Sai hoàn toàn về vòng đời. - D.
aws ecr create-service— sai namespace:ecrlà Elastic Container REGISTRY (kho chứa Docker image), không phải Elastic Container Service. ECR không có lệnhcreate-service. - C.
docker-compose create— công cụ của Docker, không phải AWS CLI. (Có Docker Compose ECS integration cho phépdocker compose uptriển khai lên ECS, nhưng cú pháp trong phương án không đúng và đề yêu cầu rõ là dùng AWS CLI.)
Ghi nhớ
Bộ khái niệm ECS: | Khái niệm | Là gì | |---|---| | Task definition | bản thiết kế: image, CPU, bộ nhớ, cổng, biến môi trường | | Task | một bản đang chạy của task definition | | Service | giữ N task luôn chạy, gắn được load balancer | | Cluster | nhóm logic chứa task và service |
Và phân biệt hai namespace hay bị lẫn: aws ecs (chạy container) và aws ecr (lưu image). Đây là bẫy xuất hiện khá thường xuyên trong đề.
An e-commerce company has deployed its application on AWS Elastic Beanstalk. The Auto Scaling group associated with the Beanstalk environment has three Amazon EC2 instances. When the number of instances falls below two, it severely impacts the performance of the web application. The company currently uses the default all-at-once deployment policy and is looking for an effective strategy for future deployments.
Which of the following represents the most cost-effective deployment strategy for the company?
-
A
Opt for rolling with additional batch deployment strategy. Set the batch size parameter to 1
-
B
Configure an Elastic Load Balancer to front the Auto Scaling Group and choose two different Availability Zones (AZs) for deployment
-
C
Opt for rolling deployment strategy. Set the batch size to 2
-
D
Opt for traffic-splitting deployment strategy with traffic split parameter set to 50% of the total traffic
Xem giải thích
Đáp án
A — Dùng rolling with additional batch, đặt batch size = 1.
Vì sao đúng
Ràng buộc quan trọng nhất: số instance không được xuống dưới 2, trong khi nhóm chỉ có 3 instance.
So sánh các chính sách với ràng buộc đó:
| Chính sách | Số instance phục vụ trong lúc deploy |
|---|---|
| All at once (đang dùng) | 0 ❌ |
| Rolling, batch = 2 | 3 − 2 = 1 ❌ |
| Rolling, batch = 1 | 3 − 1 = 2 ✅ (vừa đủ, không dư) |
| Rolling with additional batch, batch = 1 | 3 + 1 − 1 = 3 ✅ |
Rolling with additional batch dựng thêm một lô mới trước, rồi mới bắt đầu thay thế. Nhờ lô dư đó, năng lực không bao giờ tụt xuống dưới 3 — vượt xa ngưỡng 2 mà đề yêu cầu, và có biên an toàn nếu một instance khác gặp sự cố giữa chừng.
Chi phí thêm cũng tối thiểu: chỉ một instance dư trong thời gian deploy.
Vì sao các phương án khác sai
- C. Rolling với batch size = 2 — thay 2 trong 3 instance cùng lúc, còn lại 1 instance. Vi phạm thẳng ràng buộc "không dưới 2".
- D. Traffic splitting 50% — đây là chính sách dành cho canary release: dựng fleet mới và chia phần trăm traffic để đo lường. Nó không phải cơ chế bảo toàn năng lực, và với 3 instance thì việc chia 50/50 traffic không giải quyết vấn đề số instance đang phục vụ.
- B. Thêm Elastic Load Balancer và hai AZ — cải thiện tính sẵn sàng (chống hỏng AZ), nhưng không liên quan tới vấn đề deploy. Đề nói rõ vấn đề nằm ở chính sách triển khai, và ALB không ngăn được việc all-at-once hạ toàn bộ instance.
Ghi nhớ
Bảng đầy đủ các chính sách deploy của Elastic Beanstalk: | Chính sách | Thời gian chết | Năng lực trong lúc deploy | Chi phí thêm | |---|---|---|---| | All at once | có | 0% | không | | Rolling | không | giảm | không | | Rolling with additional batch | không | 100% | +1 lô | | Immutable | không | 100% | gấp đôi | | Blue/Green | không | 100% | gấp đôi |
Nguyên tắc chọn: nhóm nhỏ và có ngưỡng năng lực tối thiểu ⇒ rolling with additional batch. Với nhóm chỉ 3 instance, rolling thuần luôn cắt quá sâu.
A popular mobile app retrieves data from an AWS DynamoDB table that was provisioned with read-capacity units (RCU’s) that are evenly shared across four partitions. One of those partitions is receiving more traffic than the other partitions, causing hot partition issues.
What technology will allow you to reduce the read traffic on your AWS DynamoDB table with minimal effort?
-
A
DynamoDB DAX
-
B
More partitions
-
C
DynamoDB Streams
-
D
ElastiCache
Xem giải thích
Đáp án
A — DynamoDB DAX (DynamoDB Accelerator).
Vì sao đúng
Yêu cầu: giảm tải đọc cho bảng DynamoDB đang bị hot partition, với công sức tối thiểu.
DAX là cache trong bộ nhớ được thiết kế riêng cho DynamoDB, và điểm mạnh nhất của nó chính là "minimal effort":
| Đặc điểm | DAX |
|---|---|
| API tương thích DynamoDB | ✅ chỉ đổi endpoint, không đổi mã |
| Độ trễ | micro giây (so với mili giây của DynamoDB) |
| Giảm RCU tiêu thụ | ✅ request trúng cache không tính RCU |
| Được quản lý hoàn toàn | ✅ |
Việc tích hợp chỉ là đổi client:
# Trước
import boto3
db = boto3.resource('dynamodb')
# Sau — cùng API, khác endpoint
import amazondax
db = amazondax.AmazonDaxClient.resource(endpoint_url='dax://cum.abc.dax-clusters...')
Với hot partition, DAX giúp trực tiếp: request lặp lại vào cùng những item nóng được phục vụ từ cache, không chạm tới bảng, nên áp lực lên partition đó giảm mạnh.
DAX có hai loại cache: item cache (kết quả GetItem, BatchGetItem) và query cache (kết quả Query, Scan).
Vì sao các phương án khác sai
- D. ElastiCache — cache tốt và nhanh, nhưng không tương thích API với DynamoDB. Bạn phải tự viết toàn bộ logic cache-aside: đọc cache trước, trượt thì đọc DynamoDB rồi ghi lại cache, và tự xử lý vô hiệu hoá cache khi dữ liệu đổi. Đó là nhiều công sức phát triển — trái với "minimal effort".
- B. "Thêm partition" — bạn không kiểm soát số partition của DynamoDB. Số partition do dịch vụ tự quyết định dựa trên dung lượng dữ liệu và throughput đã cấp. Và tăng partition không sửa được phân bố khoá lệch — dữ liệu vẫn dồn vào cùng một chỗ.
- C. DynamoDB Streams — ghi lại thay đổi dữ liệu để hệ khác tiêu thụ (nhân bản, kiểm toán, kích hoạt nghiệp vụ). Nó không giảm tải đọc chút nào.
Ghi nhớ
| DAX | ElastiCache | |
|---|---|---|
| Dành cho | chỉ DynamoDB | mọi nguồn dữ liệu |
| Sửa mã | chỉ đổi endpoint | viết logic cache-aside |
| Vô hiệu hoá cache | tự động khi ghi qua DAX | tự làm |
| Độ trễ | micro giây | dưới mili giây |
Ba lưu ý về DAX: nó chỉ hoạt động trong VPC, ghi đi qua DAX thì cache mới tự cập nhật (ghi thẳng vào DynamoDB sẽ làm cache cũ), và nó eventually consistent — cần đọc nhất quán mạnh thì phải gọi thẳng DynamoDB.
A data analytics company ingests a large number of messages and stores them in an RDS database using Lambda. Because of the increased payload size, it is taking more than 15 minutes to process each message.
As a Developer Associate, which of the following options would you recommend to process each message in the MOST scalable way?
-
A
Provision an EC2 instance to poll the messages from an SQS queue
-
B
Provision EC2 instances in an Auto Scaling group to poll the messages from an SQS queue
-
C
Use DynamoDB instead of RDS as database
-
D
Contact AWS Support to increase the Lambda timeout to 60 minutes
Xem giải thích
Đáp án
B — Dựng EC2 instance trong Auto Scaling group để kéo message từ SQS queue.
Vì sao đúng
Điểm chặn rõ ràng: xử lý mỗi message mất hơn 15 phút, mà timeout tối đa của Lambda là 15 phút — giới hạn cứng, không nâng được.
Nên phải chuyển sang một nền tảng tính toán không có trần đó. Và giữa hai phương án EC2, Auto Scaling group là lựa chọn đúng vì đề đòi "MOST scalable":
SQS queue → Auto Scaling group (nhiều EC2 consumer)
↑ scale theo backlog per instance
Chính sách mở rộng nên dùng backlog per instance, không phải CPU:
backlogPerInstance = ApproximateNumberOfMessagesVisible / số instance đang chạy
Đặt target tracking với giá trị mục tiêu bằng số message mỗi instance xử lý được trong thời gian chấp nhận được. Hàng đợi dài ra thì thêm máy, ngắn lại thì bớt máy.
Vì sao dùng backlog chứ không dùng CPU: consumer chờ I/O (ghi vào RDS) nhiều hơn là tính toán, nên CPU có thể thấp trong khi hàng đợi phình ra — scale theo CPU sẽ không bao giờ kích hoạt.
Vì sao các phương án khác sai
- A. Một EC2 instance polling — chạy được, nhưng không mở rộng: tải tăng thì hàng đợi dài mãi, và nó còn là điểm hỏng đơn lẻ. Trượt tiêu chí "most scalable".
- D. Xin AWS tăng timeout Lambda lên 60 phút — 15 phút là giới hạn cứng của dịch vụ, không phải service quota để xin nâng. AWS không cấp ngoại lệ cho điều này.
- C. Đổi RDS sang DynamoDB — thay CSDL không rút ngắn thời gian xử lý payload. Đề nói rõ nguyên nhân là kích thước payload tăng, không phải CSDL chậm. Và đây là cuộc di trú lớn cho một vấn đề không nằm ở đó.
Ghi nhớ
Chọn nền tảng tính toán theo thời lượng công việc: | Thời lượng | Nền tảng | |---|---| | ≤ 15 phút | Lambda | | Dài hơn, container hoá được | ECS/Fargate | | Dài hơn, cần kiểm soát máy | EC2 + Auto Scaling | | Job theo lô, hàng loạt | AWS Batch | | Quy trình nhiều bước, chờ lâu | Step Functions (Standard: tới 1 năm) |
Và nhớ nguyên tắc mở rộng theo hàng đợi: dùng metric backlog per instance, không dùng CPU — CPU không phản ánh nút thắt khi consumer chờ I/O.