Ngân hàng đề — AWS Certified Solutions Architect Professional

Tìm thấy 1221 câu.

Câu 491 AWS Application Integration

A solution is required for updating user metadata and will be initiated by a fleet of front-end web servers. The solution must be capable of scaling rapidly from hundreds to tens of thousands of jobs in less than a minute. The solution must be asynchronous and minimize costs.

Which solution should a Solutions Architect use to meet these requirements?

  1. A

    Create an Amazon EC2 Auto Scaling group of EC2 instances that pull messages from an Amazon SQS queue and process the user metadata updates. Configure the web application to send jobs to the queue.

  2. B

    Create an AWS CloudFormation stack that is updated by an AWS Lambda function. Configure the Lambda function to update the metadata.

  3. C

    Create an AWS Lambda function that will update user metadata. Create an Amazon SQS queue and configure it as an event source for the Lambda function. Update the web application to send jobs to the queue.

  4. D

    Create an AWS Lambda function that will update user metadata. Create AWS Step Functions that will trigger the Lambda function. Update the web application to initiate Step Functions for every job.

Xem giải thích

Đáp án

**C — Tạo một hàm AWS Lambda cập nhật siêu dữ liệu người dùng; tạo một hàng đợi Amazon SQS và cấu hình nó làm event source cho hàm Lambda; sửa ứng dụng web để đẩy việc vào hàng đợi.

Vì sao đúng

Đề đòi bốn thứ, và tổ hợp này đáp ứng cả bốn: | Yêu cầu | Cách đáp ứng | |---|---| | Co giãn từ hàng trăm lên hàng chục nghìn dưới một phút | Lambda co giãn tức thì | | Bất đồng bộ | SQS tách rời | | Giảm chi phí tối đa | không có máy nào chạy khi rảnh | | Khởi tạo từ nhiều web server | nhiều nguồn cùng đẩy vào một hàng đợi |

⚠ Điểm mấu chốt: Lambda co giãn theo giây, EC2 theo phút:

Lambda + SQS
        ↓
    5 lời gọi đồng thời đầu tiên
        ↓
    Tăng thêm tới 1.000 mỗi 10 giây
    (hoặc 300 tuỳ Region)
        ↓
    → hàng chục nghìn trong dưới một
      phút
Auto Scaling group EC2
        ↓
    Cảnh báo CloudWatch cần ≥1 chu kỳ
      (60 giây)
        ↓
    Khởi chạy instance: 1-3 phút
        ↓
    Khởi động ứng dụng: thêm vài phút
    → không kịp trong một phút

⚠ Và đó là lý do phương án A không đạt:

A dùng EC2 Auto Scaling group thăm dò
  SQS
        ↓
    Kiến trúc đúng
        ↓
    Nhưng tốc độ co giãn không đáp ứng
      yêu cầu
        ↓
    Và trả tiền cho máy chạy cả lúc
      rảnh
    → đề nói "giảm chi phí tối đa"

Nối SQS làm event source:

aws lambda create-event-source-mapping \
  --function-name cap-nhat-sieu-du-lieu \
  --event-source-arn <arn-sqs> \
  --batch-size 10 \
  --maximum-batching-window-in-seconds 0 \
  --function-response-types ReportBatchItemFailures

⚠ Và Lambda TỰ thăm dò hàng đợi — không phải bạn viết:

Không cần vòng lặp `receive-message`
        ↓
    Không cần gọi `delete-message`
        ↓
    Lambda tự làm: thăm dò, gọi hàm,
      xoá thông điệp khi thành công
    → đây là "ít mã nhất"

Hàm cập nhật:

import json, os, boto3

bang = boto3.resource('dynamodb').Table(os.environ['TEN_BANG'])

def handler(su_kien, ngu_canh):
    hong = []
    for ban_ghi in su_kien['Records']:
        try:
            d = json.loads(ban_ghi['body'])
            bang.update_item(
                Key={'maNguoiDung': d['maNguoiDung']},
                UpdateExpression='SET #tt = :v, capNhatLuc = :t',
                ExpressionAttributeNames={'#tt': 'thuocTinh'},
                ExpressionAttributeValues={
                    ':v': d['thuocTinh'], ':t': d['thoiGian']})
        except Exception:
            hong.append({'itemIdentifier': ban_ghi['messageId']})
    return {'batchItemFailures': hong}

⚠ Và vì sao phương án D sai — Step Functions cho MỖI việc là lãng phí:

D tạo Step Functions kích hoạt Lambda
  cho từng việc
        ↓
    Step Functions Standard tính tiền
      theo BƯỚC CHUYỂN TRẠNG THÁI
        ↓
    0,025 USD mỗi 1.000 bước
        ↓
    Hàng chục nghìn việc
    → đắt hơn nhiều so với SQS

So sánh chi phí cho 1 triệu việc: | Cách | Chi phí xấp xỉ | |---|---| | SQS + Lambda | 0,40 USD (SQS) + phí Lambda | | Step Functions Standard | 25 USD chỉ riêng bước chuyển | | Step Functions Express | rẻ hơn nhiều nhưng vẫn hơn SQS |

⚠ Và Step Functions giải quyết bài toán KHÁC:

Step Functions dùng khi:
    - nhiều bước có thứ tự
    - cần rẽ nhánh, thử lại theo bước
    - cần theo dõi trạng thái từng
      luồng
        ↓
    Ở đây chỉ có MỘT bước
    → không cần điều phối

⚠ Và Step Functions cũng không tách rời tốt bằng hàng đợi:

Web server gọi `StartExecution`
        ↓
    Nếu Step Functions bị throttle
        ↓
    Web server phải tự xử lý lỗi và
      thử lại
        ↓
    Hàng đợi hấp thụ được đỉnh
    → và giữ việc lại nếu hạ nguồn
      chết

⚠ Và vì sao phương án B vô lý:

B tạo CloudFormation stack được Lambda
  cập nhật
        ↓
    CloudFormation quản HẠ TẦNG
        ↓
    Không phải nơi lưu siêu dữ liệu
      người dùng
        ↓
    Và cập nhật stack mất vài phút mỗi
      lần
    → không dùng cho hàng chục nghìn
      thao tác

⚠ Và mức đồng thời của Lambda có giới hạn:

Mặc định 1.000 đồng thời mỗi Region
        ↓
    Chia chung cho MỌI hàm
        ↓
    Hàng chục nghìn việc cùng lúc
    → phải xin tăng hạn ngạch
aws service-quotas request-service-quota-increase \
  --service-code lambda \
  --quota-code L-B99A9384 \
  --desired-value 5000

⚠ Và tốc độ tăng đồng thời cũng có giới hạn:

Khởi đầu: tới 1.000 đồng thời ngay
        ↓
    Sau đó: +1.000 mỗi 10 giây (Region
      lớn)
        ↓
    → hàng chục nghìn trong khoảng một
      phút
    → đúng như đề yêu cầu

⚠ Và với SQS thì Lambda tăng theo nhịp riêng:

Lambda tăng 60 instance mỗi phút cho
  mỗi event source SQS chuẩn
        ↓
    Đây từng là giới hạn đáng kể
        ↓
    Từ 2023 nâng lên 300 mỗi phút
    → nhanh hơn nhiều

⚠ Và nên đặt reserved concurrency nếu hạ nguồn yếu:

aws lambda put-function-concurrency \
  --function-name cap-nhat-sieu-du-lieu \
  --reserved-concurrent-executions 500
Bảo đảm hàm này luôn có 500
        ↓
    Và chặn nó ở 500
    → bảo vệ CSDL hạ nguồn

⚠ Và visibility timeout phải ≥ 6 lần timeout của hàm:

aws sqs set-queue-attributes --queue-url <url> \
  --attributes VisibilityTimeout=180
Hàm timeout 30 giây
        ↓
    Visibility timeout 180 giây
        ↓
    Đây là khuyến nghị của AWS
    → tránh xử lý trùng khi có thử lại

⚠ Và phải có dead-letter queue:

aws sqs set-queue-attributes --queue-url <url> \
  --attributes '{"RedrivePolicy":
    "{\"deadLetterTargetArn\":\"<arn-dlq>\",\"maxReceiveCount\":\"3\"}"}'

⚠ Và xử lý phải idempotent:

SQS chuẩn giao ít nhất một lần
        ↓
    Cùng một cập nhật có thể chạy hai
      lần
        ↓
    `SET` giá trị cố định → an toàn
        ↓
    `ADD` cộng dồn → SAI khi chạy lại

⚠ Và nếu cần đúng một lần thì dùng FIFO:

aws sqs create-queue --queue-name viec.fifo \
  --attributes '{"FifoQueue": "true",
                 "ContentBasedDeduplication": "true",
                 "FifoThroughputLimit": "perMessageGroupId",
                 "DeduplicationScope": "messageGroup"}'
Nhưng FIFO chuẩn chỉ 300 thao tác
  mỗi giây
        ↓
    High-throughput mode: hàng chục
      nghìn
        ↓
    → cần cấu hình đúng hai thuộc tính
      trên

⚠ Và ứng dụng web đẩy vào hàng đợi theo lô sẽ rẻ hơn:

sqs.send_message_batch(
    QueueUrl=URL,
    Entries=[{'Id': str(i), 'MessageBody': json.dumps(v)}
             for i, v in enumerate(danh_sach[:10])])
`SendMessageBatch` gửi tối đa 10 mỗi
  lời gọi
        ↓
    Giảm 10 lần số yêu cầu API
    → và SQS tính tiền theo yêu cầu

Ba lợi ích: | Lợi ích | Chi tiết | |---|---| | Co giãn từ 0 lên hàng chục nghìn trong giây | | | Không trả tiền khi rảnh | | | Không phải viết vòng lặp thăm dò | |

⚠ Và nên theo dõi IteratorAge tương đương:

aws cloudwatch put-metric-alarm \
  --alarm-name viec-ton-dong \
  --namespace AWS/SQS \
  --metric-name ApproximateAgeOfOldestMessage \
  --dimensions Name=QueueName,Value=viec \
  --statistic Maximum --period 60 \
  --threshold 300 --comparison-operator GreaterThanThreshold \
  --evaluation-periods 2 --alarm-actions <arn-sns>

Vì sao các phương án khác sai

  • **A. EC2 Auto Scaling group thăm dò SQS và xử lý — đây là phương án gần nhất và kiến trúc hàng đợi + worker hoàn toàn hợp lý, nhưng EC2 mất vài phút để khởi chạy nên không co giãn kịp trong dưới một phút, và phải trả tiền cho máy chạy cả lúc không có việc.
  • **D. Step Functions kích hoạt Lambda cho mỗi việc — Step Functions tính tiền theo bước chuyển trạng thái, đắt hơn nhiều cho hàng chục nghìn việc một bước, và không tách rời tốt bằng hàng đợi.
  • **B. CloudFormation stack được Lambda cập nhật — CloudFormation quản hạ tầng, không phải nơi lưu siêu dữ liệu người dùng.

Ghi nhớ

⚠ Bốn cách xử lý việc bất đồng bộ — bảng phải thuộc: | Cách | Tốc độ co giãn | Chi phí khi rảnh | |---|---|---| | SQS + Lambda | giây | 0 | | SQS + EC2 ASG | phút | theo giờ | | SQS + Fargate | chục giây | 0 nếu về 0 task | | Step Functions | giây | 0 nhưng đắt theo bước |

Từ khoá nhận diện:

"hundreds to tens of thousands in under a minute" → Lambda "asynchronous, minimize cost" → SQS + Lambda "orchestrate multiple steps" → Step Functions "long-running over 15 minutes" → Fargate hoặc Batch

Ba lưu ý về Lambda + SQS: | Lưu ý | Chi tiết | |---|---| | Lambda tự thăm dò và tự xoá thông điệp | | | Visibility timeout ≥ 6 lần timeout hàm | | | ReportBatchItemFailures tránh xử lý lại cả lô | |

Ba lưu ý về đồng thời: | Lưu ý | Chi tiết | |---|---| | Mặc định 1.000 mỗi Region, chia chung | | | Tăng 1.000 mỗi 10 giây | | | Reserved concurrency vừa bảo đảm vừa giới hạn | |

Ba lưu ý về idempotency: | Lưu ý | Chi tiết | |---|---| | SQS chuẩn giao ít nhất một lần | | | SET an toàn, ADD thì không | | | FIFO nếu cần đúng một lần | |

Ba lưu ý về FIFO: | Lưu ý | Chi tiết | |---|---| | Mặc định 300 thao tác/giây | | | High-throughput cần hai thuộc tính cấu hình | | | MessageGroupId quyết định thứ tự | |

Ba lưu ý về chi phí: | Lưu ý | Chi tiết | |---|---| | SendMessageBatch giảm 10 lần số yêu cầu | | | Long polling giảm lời gọi rỗng | | | Lambda ARM rẻ hơn ~20% | |

Ba lưu ý về độ tin cậy: | Lưu ý | Chi tiết | |---|---| | Dead-letter queue là bắt buộc | | | Cảnh báo cho DLQ | | | Theo dõi ApproximateAgeOfOldestMessage | |

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Đẩy 10.000 việc, đo thời gian xử lý hết | | | Xem ConcurrentExecutions lúc đỉnh | | | Kiểm DLQ có rỗng không | |

Và một lời khuyên: hãy kiểm tra hạn ngạch đồng thời của Lambda trong Region trước khi hứa hẹn con số hàng chục nghìn. Mặc định 1.000 được chia chung cho mọi hàm trong tài khoản — nên một đợt tải đúng như thiết kế vẫn có thể bị throttle chỉ vì một hàm khác đang chiếm phần lớn hạn mức.

Câu 492 AWS Application Integration

A company is migrating an order processing application to the AWS Cloud. The usage patterns vary significantly but the application must be available at all times. Orders must be processed immediately and in the order that they are received. Which actions should a Solutions Architect take to meet these requirements?

  1. A

    Use Amazon SNS with FIFO to send orders in the correct order. Use Spot Instances in multiple Availability Zones for processing.

  2. B

    Use Amazon SNS with FIFO to send orders in the correct order. Use a single large Reserved Instance for processing.

  3. C

    Use Amazon SQS with FIFO to queue messages in the correct order. Use Spot Instances in multiple Availability Zones for processing.

  4. D

    Use Amazon SQS with FIFO to queue messages in the correct order. Use Reserved Instances in multiple Availability Zones for processing.

Xem giải thích

Đáp án

**D — Dùng Amazon SQS FIFO để xếp thông điệp đúng thứ tự; dùng Reserved Instance ở nhiều Availability Zone để xử lý.

Vì sao đúng

Đề có ba ràng buộc, và mỗi vế của đáp án lo một phần: | Ràng buộc | Cách đáp ứng | |---|---| | Xử lý đúng thứ tự nhận | SQS FIFO | | Phải luôn sẵn sàng | nhiều AZ + Reserved Instance | | Xử lý ngay lập tức | máy luôn chạy, không chờ khởi động |

⚠ Điểm mấu chốt: SNS không phải hàng đợi:

SNS là mô hình phát hành–đăng ký
        ↓
    Nó ĐẨY thông điệp tới người đăng ký
        ↓
    Không lưu lại nếu không ai nhận
      được
        ↓
    → không có khái niệm "xếp hàng chờ
      xử lý"
Đề nói "đơn hàng phải được xử lý
  ngay và ĐÚNG THỨ TỰ NHẬN"
        ↓
    Cần một HÀNG ĐỢI
    → phương án A và B loại ngay

⚠ Và SNS FIFO tồn tại nhưng dùng khác:

SNS FIFO topic chỉ đẩy được tới SQS
  FIFO queue
        ↓
    Nó bảo toàn thứ tự khi FANOUT tới
      nhiều hàng đợi
        ↓
    Vẫn phải có SQS FIFO ở cuối
    → SNS một mình không xử lý đơn
      hàng được

Bảng phân biệt: | | SNS | SQS | |---|---|---| | Mô hình | đẩy (push) | kéo (pull) | | Lưu trữ | không | tới 14 ngày | | Nhiều người nhận | có, tất cả đều nhận | mỗi thông điệp một người xử lý | | Thử lại | theo chính sách retry | tự động, có DLQ |

⚠ Điểm mấu chốt thứ hai: Spot không hợp với "phải luôn sẵn sàng":

Đề nói "ứng dụng phải sẵn sàng mọi
  lúc"
        ↓
    Spot Instance bị thu hồi với thông
      báo trước 2 phút
        ↓
    Giá tăng hoặc AWS cần công suất
        ↓
    → có thể mất toàn bộ đội máy cùng
      lúc
    → phương án C loại

⚠ Và đó là điểm phân biệt duy nhất giữa C và D:

C: SQS FIFO + Spot
D: SQS FIFO + Reserved Instance
        ↓
    Cả hai đều đúng phần hàng đợi
    → chỉ khác loại máy tính

Bảng ba mô hình mua EC2: | Mô hình | Cam kết | Rủi ro gián đoạn | |---|---|---| | On-Demand | không | không | | Reserved / Savings Plan | 1-3 năm | không | | Spot | không | thu hồi bất kỳ lúc nào |

"Mô hình sử dụng dao động đáng kể"
        ↓
    Nghe như hợp với Spot
        ↓
    Nhưng "phải sẵn sàng mọi lúc" đè
      lên
    → Reserved cho phần nền, On-Demand
      cho đỉnh

⚠ Và thực tế nên kết hợp cả hai:

{"MixedInstancesPolicy": {
  "InstancesDistribution": {
    "OnDemandBaseCapacity": 4,
    "OnDemandPercentageAboveBaseCapacity": 30,
    "SpotAllocationStrategy": "capacity-optimized"},
  "LaunchTemplate": {"Overrides": [
    {"InstanceType": "m6i.large"},
    {"InstanceType": "m5.large"},
    {"InstanceType": "m6a.large"}]}}}
4 máy On-Demand làm nền
        ↓
    Phần trên: 30% On-Demand, 70% Spot
        ↓
    Spot bị thu hồi → nền vẫn chạy
    → vừa rẻ vừa sẵn sàng

Tạo hàng đợi FIFO:

aws sqs create-queue --queue-name don-hang.fifo \
  --attributes '{
    "FifoQueue": "true",
    "ContentBasedDeduplication": "false",
    "VisibilityTimeout": "300",
    "MessageRetentionPeriod": "345600",
    "DeduplicationScope": "messageGroup",
    "FifoThroughputLimit": "perMessageGroupId"}'

⚠ Và tên hàng đợi FIFO PHẢI kết thúc bằng .fifo:

Thiếu hậu tố
        ↓
    Lệnh tạo thất bại
        ↓
    Và không đổi hàng đợi chuẩn thành
      FIFO được
    → phải tạo mới

Gửi thông điệp:

aws sqs send-message \
  --queue-url <url-fifo> \
  --message-body '{"maDon":"DH-1001","maKhach":"KH-55"}' \
  --message-group-id "KH-55" \
  --message-deduplication-id "DH-1001"

⚠ Và MessageGroupId là khái niệm quan trọng nhất của FIFO:

Thứ tự chỉ bảo đảm TRONG một nhóm
        ↓
    Các nhóm khác nhau xử lý song song
        ↓
    Dùng mã khách hàng làm nhóm
    → đơn của mỗi khách đúng thứ tự
    → và nhiều khách xử lý cùng lúc
Dùng một nhóm duy nhất cho tất cả
        ↓
    Thứ tự tuyệt đối
        ↓
    Nhưng chỉ MỘT người xử lý tại một
      thời điểm
    → thông lượng rất thấp

⚠ Và đó là đánh đổi cơ bản của FIFO: | Số nhóm | Thứ tự | Thông lượng | |---|---|---| | 1 nhóm | tuyệt đối | rất thấp | | Nhiều nhóm | trong từng nhóm | cao |

⚠ Và thông lượng FIFO có giới hạn cần biết:

Mặc định: 300 thao tác/giây
        ↓
    Với batching: 3.000 thông điệp/giây
        ↓
    High-throughput mode:
      tới 70.000 thông điệp/giây
        ↓
    → cần đặt `DeduplicationScope` và
      `FifoThroughputLimit`

⚠ Và khử trùng lặp có cửa sổ 5 phút:

Gửi cùng `MessageDeduplicationId`
  trong 5 phút
        ↓
    Thông điệp thứ hai bị BỎ QUA im
      lặng
        ↓
    Không có lỗi nào
    → đúng khi chống trùng
    → nhưng gây bối rối nếu vô tình
      trùng id

⚠ Và ContentBasedDeduplication băm nội dung:

Bật lên → không cần khai
  `MessageDeduplicationId`
        ↓
    SQS băm SHA-256 nội dung thông
      điệp
        ↓
    Hai đơn hàng nội dung giống hệt
      trong 5 phút
    → cái sau bị bỏ
    → nguy hiểm nếu đơn hàng có thể
      trùng nội dung thật

Nhận và xử lý:

import boto3, json

sqs = boto3.client('sqs')

while True:
    kq = sqs.receive_message(
        QueueUrl=URL, MaxNumberOfMessages=10,
        WaitTimeSeconds=20,
        AttributeNames=['MessageGroupId'])
    for tin in kq.get('Messages', []):
        don = json.loads(tin['Body'])
        xu_ly(don)
        sqs.delete_message(QueueUrl=URL,
                           ReceiptHandle=tin['ReceiptHandle'])

⚠ Và FIFO chặn nhóm khi có thông điệp lỗi:

Thông điệp đầu nhóm xử lý thất bại
        ↓
    Nó quay lại hàng đợi
        ↓
    Các thông điệp sau trong CÙNG NHÓM
      bị chặn
        ↓
    → đây là hệ quả tất yếu của việc
      giữ thứ tự
    → phải có DLQ để nhóm không kẹt
      mãi

⚠ Và Multi-AZ là yêu cầu tối thiểu cho sẵn sàng:

Một AZ hỏng
        ↓
    Máy ở AZ khác vẫn xử lý
        ↓
    SQS vốn đã là dịch vụ nhiều AZ
    → chỉ tầng tính toán cần lo

Ba lợi ích: | Lợi ích | Chi tiết | |---|---| | Thứ tự được bảo đảm trong nhóm | | | Không mất đơn hàng nào | | | Sống sót qua sự cố một AZ | |

⚠ Và nếu tải dao động mạnh thì Savings Plan linh hoạt hơn RI:

Compute Savings Plan
        ↓
    Áp cho EC2, Fargate, Lambda
        ↓
    Không khoá vào loại instance cụ
      thể
    → linh hoạt hơn Reserved Instance
      chuẩn

Vì sao các phương án khác sai

  • **C. SQS FIFO + Spot Instance ở nhiều AZ — đây là phương án gần nhất và phần hàng đợi hoàn toàn đúng, nhưng Spot bị thu hồi với thông báo trước hai phút, trái với yêu cầu "ứng dụng phải sẵn sàng mọi lúc".
  • **A. SNS FIFO + Spot ở nhiều AZ — SNS là mô hình đẩy, không lưu thông điệp chờ xử lý; và Spot không đảm bảo sẵn sàng.
  • **B. SNS FIFO + một Reserved Instance lớn duy nhất — ngoài vấn đề SNS, một instance duy nhất là điểm hỏng đơn lẻ.

Ghi nhớ

⚠ Bốn điều về SQS FIFO — bảng phải thuộc: | Điều | Chi tiết | |---|---| | Tên phải kết thúc .fifo | không đổi từ hàng đợi chuẩn được | | Thứ tự trong MessageGroupId | các nhóm chạy song song | | Khử trùng lặp cửa sổ 5 phút | bỏ qua im lặng | | High-throughput mode | cần hai thuộc tính cấu hình |

Từ khoá nhận diện:

"process in the order received" → SQS FIFO "must be available at all times" → KHÔNG dùng Spot "fanout to multiple subscribers" → SNS "varying usage patterns" → kết hợp RI nền + On-Demand đỉnh

Ba lưu ý về MessageGroupId: | Lưu ý | Chi tiết | |---|---| | Một nhóm = một người xử lý tại một thời điểm | | | Nhiều nhóm = song song | | | Chọn khoá nghiệp vụ hợp lý (mã khách, mã tài khoản) | |

Ba lưu ý về thông lượng FIFO: | Chế độ | Giới hạn | |---|---| | Mặc định | 300 thao tác/giây | | Với batching | 3.000 thông điệp/giây | | High-throughput | tới 70.000 thông điệp/giây |

Ba lưu ý về Spot: | Lưu ý | Chi tiết | |---|---| | Thu hồi báo trước 2 phút | | | Chỉ dùng cho việc chịu được gián đoạn | | | Đa dạng loại instance giảm rủi ro | |

Ba lưu ý về SNS và SQS: | Lưu ý | Chi tiết | |---|---| | SNS đẩy, SQS kéo | | | SNS không lưu thông điệp | | | SNS FIFO chỉ đẩy tới SQS FIFO | |

Ba lưu ý về chặn nhóm: | Lưu ý | Chi tiết | |---|---| | Thông điệp lỗi chặn cả nhóm | | | DLQ giải phóng nhóm sau maxReceiveCount | | | Đây là cái giá của việc giữ thứ tự | |

Ba lưu ý về sẵn sàng: | Lưu ý | Chi tiết | |---|---| | Tối thiểu hai AZ | | | Không dùng một instance duy nhất | | | SQS vốn đã nhiều AZ | |

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Gửi 100 đơn cùng nhóm, kiểm thứ tự xử lý | | | Giết một AZ thử, xem còn xử lý không | | | Kiểm DLQ khi có thông điệp lỗi | |

Và một lời khuyên: hãy chọn MessageGroupId theo khoá nghiệp vụ hẹp nhất mà vẫn đủ đảm bảo thứ tự. Rất nhiều hệ thống FIFO chạy chậm như rùa vì dùng một hằng số làm group id — thứ tự thì tuyệt đối, nhưng toàn bộ hàng đợi chỉ có đúng một người xử lý tại một thời điểm.

Câu 493 Chọn nhiều đáp án AWS Networking & Content Delivery

A company is using multiple AWS accounts. The company’s DNS records are stored in a private Amazon Route 53 hosted zone in the management account and their applications are running in a production account.

A Solutions Architect is attempting to deploy an application into the production account. The application must resolve a CNAME record set for an Amazon RDS endpoint. The CNAME record set was created in a private hosted zone in the management account.

The deployment failed to start and the Solutions Architect has discovered that the CNAME record is not resolvable on the application EC2 instance despite being correctly created in Route 53.

Which combination of steps should the Solutions Architect take to resolve this issue? (Select TWO.)

  1. A

    Create a private hosted zone for the record set in the production account. Configure Route 53 replication between AWS accounts.

  2. B

    Deploy the database on a separate EC2 instance in the new VPC. Create a record set for the instance's private IP in the private hosted zone.

  3. C

    Associate a new VPC in the production account with a hosted zone in the management account. Delete the association authorization in the management account.

  4. D

    Hardcode the DNS name and IP address of the RDS database instance into the /etc/resolv.conf file on the application server.

  5. E

    Create an authorization to associate the private hosted zone in the management account with the new VPC in the production account.

Xem giải thích

Đáp án

**C và E — Tạo một authorization để liên kết private hosted zone ở tài khoản quản lý với VPC mới ở tài khoản production; rồi liên kết VPC đó với hosted zone và xoá authorization ở tài khoản quản lý.

Vì sao đúng

Private hosted zone chỉ phân giải được cho các VPC đã được liên kết tường minh. Liên kết liên tài khoản là quy trình hai bước, và hai mệnh đề đúng chính là hai bước đó.

⚠ Điểm mấu chốt: private hosted zone không tự động dùng chung giữa các tài khoản:

Hosted zone ở tài khoản quản lý
        ↓
    EC2 ở tài khoản production
        ↓
    Không liên kết → không phân giải
      được
        ↓
    Bản ghi vẫn tồn tại, cấu hình vẫn
      đúng
    → nhưng `dig` trả về NXDOMAIN

Bước 1 — ở tài khoản chứa hosted zone:

aws route53 create-vpc-association-authorization \
  --hosted-zone-id Z0123456789ABC \
  --vpc VPCRegion=ap-southeast-1,VPCId=vpc-production

Bước 2 — ở tài khoản chứa VPC:

aws route53 associate-vpc-with-hosted-zone \
  --hosted-zone-id Z0123456789ABC \
  --vpc VPCRegion=ap-southeast-1,VPCId=vpc-production

Bước 3 — dọn dẹp ở tài khoản chứa hosted zone:

aws route53 delete-vpc-association-authorization \
  --hosted-zone-id Z0123456789ABC \
  --vpc VPCRegion=ap-southeast-1,VPCId=vpc-production

⚠ Và bước 3 là phần "xoá authorization" trong mệnh đề C:

Authorization chỉ là GIẤY PHÉP một
  lần
        ↓
    Sau khi liên kết xong, nó không
      còn tác dụng gì
        ↓
    Để lại → ai đó có thể liên kết lại
      sau khi bạn đã gỡ liên kết
    → xoá đi là thực hành tốt

⚠ Và xoá authorization KHÔNG gỡ liên kết đã tạo:

Nhiều người sợ xoá vì tưởng nó phá
  liên kết
        ↓
    Không phải
        ↓
    Liên kết đã tạo vẫn tồn tại
    → chỉ mất khả năng tạo liên kết
      MỚI

⚠ Và console KHÔNG làm được việc này:

Console của Route 53 chỉ liên kết
  được VPC trong CÙNG tài khoản
        ↓
    Liên tài khoản bắt buộc dùng CLI
      hoặc SDK
        ↓
    → đây là lý do rất nhiều người
      tưởng tính năng này không tồn
      tại

⚠ Và vì sao mệnh đề A sai — Route 53 không có "replication":

A nói tạo private hosted zone ở tài
  khoản production rồi cấu hình "Route
  53 replication between accounts"
        ↓
    Không có tính năng nào tên như vậy
        ↓
    Muốn nhân bản bản ghi → phải tự
      đồng bộ bằng script
    → và khi đó có hai nguồn sự thật

⚠ Và vì sao mệnh đề B lệch hoàn toàn:

B nói triển khai CSDL trên một EC2
  riêng trong VPC mới
        ↓
    Vấn đề là PHÂN GIẢI TÊN
        ↓
    Không phải vấn đề vị trí CSDL
        ↓
    Và RDS đã có sẵn, không việc gì
      phải chuyển sang EC2 tự quản

⚠ Và vì sao mệnh đề D là thực hành rất xấu:

D nói ghi cứng tên DNS và IP vào
  `/etc/resolv.conf`
        ↓
    Thứ nhất: `/etc/resolv.conf` khai
      MÁY CHỦ DNS, không phải ánh xạ
      tên–IP (đó là `/etc/hosts`)
        ↓
    Thứ hai: IP của RDS THAY ĐỔI khi
      chuyển đổi Multi-AZ
        ↓
    → ứng dụng trỏ vào IP cũ, mất kết
      nối

⚠ Và IP của RDS đổi là chuyện xảy ra thường xuyên:

Chuyển đổi Multi-AZ
        ↓
    Bảo trì, vá lỗi
        ↓
    Đổi kích thước instance
        ↓
    → tên DNS luôn đúng, IP thì không
    → không bao giờ ghi cứng IP của
      RDS

⚠ Và một hosted zone liên kết được với nhiều VPC:

Một private hosted zone
        ↓
    Liên kết với hàng chục VPC
        ↓
    Ở nhiều tài khoản, nhiều Region
        ↓
    → mô hình DNS tập trung
    → một nơi duy nhất quản bản ghi nội
      bộ

⚠ Và VPC phải bật hai thuộc tính DNS:

aws ec2 modify-vpc-attribute --vpc-id vpc-production \
  --enable-dns-support
aws ec2 modify-vpc-attribute --vpc-id vpc-production \
  --enable-dns-hostnames
`enableDnsSupport` tắt
        ↓
    Route 53 Resolver ở địa chỉ .2
      không hoạt động
        ↓
    Liên kết thành công nhưng vẫn
      không phân giải được
    → triệu chứng gây hiểu lầm

⚠ Và CIDR chồng lấn gây vấn đề với private hosted zone:

Hai VPC cùng liên kết một hosted zone
        ↓
    CIDR chồng lấn
        ↓
    Route 53 vẫn phân giải
        ↓
    Nhưng gói tin không định tuyến
      được tới đúng nơi
    → phân giải đúng, kết nối sai

⚠ Và khi có nhiều hosted zone trùng tên thì luật là "khớp cụ thể nhất":

Zone A: `congty.local`
        ↓
    Zone B: `db.congty.local`
        ↓
    Truy vấn `may1.db.congty.local`
        ↓
    → dùng zone B
    → giống luật của DNS thường

Kiểm chứng:

aws route53 list-hosted-zones-by-vpc \
  --vpc-id vpc-production \
  --vpc-region ap-southeast-1
dig +short may-chu-csdl.congty.local

⚠ Và có lựa chọn thứ hai: Route 53 Resolver endpoint:

aws route53resolver create-resolver-endpoint \
  --creator-request-id rq-1 \
  --security-group-ids sg-resolver \
  --direction INBOUND \
  --ip-addresses SubnetId=subnet-a SubnetId=subnet-b \
  --name endpoint-vao
Dùng khi cần phân giải từ TẠI CHỖ
        ↓
    Hoặc giữa các mạng không liên kết
      trực tiếp được
        ↓
    Đắt hơn và phức tạp hơn
    → chỉ dùng khi liên kết VPC không
      đủ

⚠ Và Resolver rule chia sẻ được qua RAM:

aws ram create-resource-share \
  --name chia-se-resolver-rule \
  --resource-arns <arn-rule> \
  --principals ou-abc-11111111
Chia sẻ luật chuyển tiếp DNS cho cả
  OU
        ↓
    Tài khoản mới tự nhận
    → mô hình DNS tập trung ở quy mô
      lớn

⚠ Và không gỡ liên kết VPC cuối cùng được:

Private hosted zone phải có ít nhất
  một VPC liên kết
        ↓
    Gỡ cái cuối → lỗi
        ↓
    Muốn bỏ hẳn → xoá cả hosted zone

Ba lợi ích của mô hình DNS tập trung: | Lợi ích | Chi tiết | |---|---| | Một nguồn sự thật cho tên nội bộ | | | Tài khoản mới chỉ cần liên kết | | | Không phải đồng bộ bản ghi giữa các nơi | |

⚠ Và nên tự động hoá bằng CloudFormation ở cả hai phía:

# Tài khoản chứa hosted zone
Authorization:
  Type: AWS::Route53::VPCAssociationAuthorization
  Properties:
    HostedZoneId: Z0123456789ABC
    VPC:
      VPCId: !Ref VpcProduction
      VPCRegion: ap-southeast-1
Nhưng CloudFormation không chạy được
  ở hai tài khoản trong một stack
        ↓
    → dùng StackSet, hoặc custom
      resource gọi chéo tài khoản

Vì sao các phương án khác sai

  • **A. Tạo private hosted zone ở tài khoản production và cấu hình Route 53 replication giữa các tài khoản — đây là phương án gần nhất và nghe rất hợp lý về mặt khái niệm, nhưng Route 53 không có tính năng nhân bản hosted zone nào; và làm vậy sẽ tạo ra hai nguồn sự thật phải tự đồng bộ.
  • **B. Triển khai CSDL trên một EC2 riêng trong VPC mới và tạo bản ghi trỏ IP riêng tư — vấn đề là phân giải tên, không phải vị trí cơ sở dữ liệu.
  • **D. Ghi cứng tên DNS và IP vào /etc/resolv.conf — sai tệp (đó là /etc/hosts), và IP của RDS thay đổi mỗi lần chuyển đổi Multi-AZ.

Ghi nhớ

⚠ Ba bước liên kết VPC liên tài khoản — bảng phải thuộc: | Bước | Ở tài khoản nào | |---|---| | create-vpc-association-authorization | tài khoản chứa hosted zone | | associate-vpc-with-hosted-zone | tài khoản chứa VPC | | delete-vpc-association-authorization | tài khoản chứa hosted zone |

Từ khoá nhận diện:

"private hosted zone in another account" → authorization + associate "Route 53 replication" → KHÔNG TỒN TẠI "resolve from on-premises" → Resolver inbound endpoint "hardcode IP in resolv.conf" → LUÔN SAI

Ba lưu ý về private hosted zone: | Lưu ý | Chi tiết | |---|---| | Chỉ phân giải cho VPC đã liên kết | | | Liên kết được nhiều VPC, nhiều tài khoản | | | Phải giữ ít nhất một VPC liên kết | |

Ba lưu ý về thuộc tính VPC: | Thuộc tính | Tác dụng | |---|---| | enableDnsSupport | dùng được Resolver ở .2 | | enableDnsHostnames | instance có tên DNS | | Thiếu một trong hai | liên kết vẫn thành công nhưng không phân giải |

Ba lưu ý về console: | Lưu ý | Chi tiết | |---|---| | Console chỉ liên kết VPC cùng tài khoản | | | Liên tài khoản bắt buộc CLI/SDK | | | Xoá authorization không gỡ liên kết | |

Ba lưu ý về Route 53 Resolver: | Loại endpoint | Dùng cho | |---|---| | Inbound | tại chỗ hỏi AWS | | Outbound | AWS hỏi tại chỗ | | Resolver rule | chuyển tiếp theo tên miền |

Ba lưu ý về RDS endpoint: | Lưu ý | Chi tiết | |---|---| | Luôn dùng tên DNS, không dùng IP | | | IP đổi khi chuyển đổi Multi-AZ | | | Aurora có writer và reader endpoint riêng | |

Ba lưu ý về nhiều hosted zone: | Lưu ý | Chi tiết | |---|---| | Khớp cụ thể nhất thắng | | | CIDR chồng lấn gây định tuyến sai | | | Chia sẻ Resolver rule qua RAM | |

Ba việc kiểm chứng: | Việc | Cách | |---|---| | list-hosted-zones-by-vpc xem đã liên kết chưa | | | dig từ instance trong VPC đó | | | Kiểm enableDnsSupport của VPC | |

Và một lời khuyên: hãy thử dig từ chính instance gặp vấn đề chứ đừng chỉ kiểm tra cấu hình trong console. Bản ghi có thể hoàn toàn đúng, hosted zone có thể đã liên kết, mà tên vẫn không phân giải được chỉ vì enableDnsSupport của VPC bị tắt — và không màn hình cấu hình nào của Route 53 cho bạn thấy điều đó.

Câu 494 AWS Database

A company requires multi-Region availability for an application that runs on Amazon EC2 instances with an Amazon RDS for MySQL database. The solution must offer the highest availability.

Which solution should a solutions architect recommend?

  1. A

    Enable global tables for the RDS database instance across multiple Regions. Store the DB endpoint in AWS Secrets Manager. In the case of an outage, update the DB endpoint in Secrets Manager to the cross-Region table endpoint.

  2. B

    Enable a multi-master cluster configuration across multiple Regions. Store the DB endpoint in AWS Secrets Manager. In the case of an outage, use AWS Lambda to update the endpoint address used by the applications.

  3. C

    Enable automated backups for the RDS database instance. In the case of an outage, promote the automated backup to be a standalone DB instance. Point applications to the new DB endpoint and create a read replica to maintain high availability.

  4. D

    Enable a cross-Region read replica for the RDS database. In the case of an outage, promote the replica to be a standalone DB instance. Point applications to the new DB endpoint and create a read replica to maintain high availability.

Xem giải thích

Đáp án

**D — Bật cross-Region read replica cho cơ sở dữ liệu RDS; khi có sự cố thì thăng cấp replica thành instance độc lập, trỏ ứng dụng sang endpoint mới và tạo một read replica khác để duy trì tính sẵn sàng.

Vì sao đúng

Đề đòi sẵn sàng nhiều Region với mức sẵn sàng cao nhất. Chỉ một phương án dựa trên tính năng thật sự tồn tại và hoạt động đúng.

⚠ Điểm mấu chốt: cross-Region read replica là cơ chế DR chuẩn của RDS:

Replica ở Region khác
        ↓
    Sao chép bất đồng bộ liên tục
        ↓
    Region chính mất
        ↓
    Thăng cấp replica → CSDL độc lập
    → RTO tính bằng phút
aws rds create-db-instance-read-replica \
  --db-instance-identifier ban-sao-us-west \
  --source-db-instance-identifier \
    arn:aws:rds:ap-southeast-1:111122223333:db:csdl-chinh \
  --region us-west-2 \
  --db-instance-class db.r6g.large \
  --multi-az

⚠ Và --multi-az cho replica là chi tiết đáng làm:

Replica cũng có thể hỏng
        ↓
    Đặt nó ở chế độ Multi-AZ
        ↓
    Sẵn sàng ở cả hai Region
    → và sau khi thăng cấp thì nó đã
      sẵn Multi-AZ

Thăng cấp khi có sự cố:

aws rds promote-read-replica \
  --db-instance-identifier ban-sao-us-west \
  --region us-west-2 \
  --backup-retention-period 7

⚠ Và tạo replica mới sau khi thăng cấp là phần quan trọng của đáp án:

Thăng cấp xong → chỉ còn MỘT bản
        ↓
    Không còn khả năng chống thảm hoạ
        ↓
    Tạo replica mới ở Region khác
    → khôi phục lại thế trận

⚠ Và vì sao phương án A sai — RDS KHÔNG có global table:

A nói "bật global tables cho RDS
  instance"
        ↓
    Global Tables là tính năng của
      DYNAMODB
        ↓
    RDS không có khái niệm này
    → mệnh đề mô tả thứ không tồn tại

Bảng những cái tên hay bị gán nhầm: | Tính năng | Thuộc về | |---|---| | Global Tables | DynamoDB | | Global Database | Aurora | | Cross-Region read replica | RDS và Aurora | | Multi-Region access point | S3 |

⚠ Và vì sao phương án B sai — RDS MySQL không có multi-master liên Region:

B nói "bật cấu hình multi-master
  cluster giữa nhiều Region"
        ↓
    Aurora từng có Multi-Master, nhưng
      chỉ TRONG một Region
        ↓
    Và đã ngừng phát triển
        ↓
    RDS for MySQL chưa bao giờ có
    → mệnh đề sai về sự thật

⚠ Và Aurora Global Database mới là thứ B đang mô tả nhầm:

aws rds create-global-cluster \
  --global-cluster-identifier cum-toan-cau \
  --source-db-cluster-identifier <arn-cum-chinh>
Aurora Global Database:
    - RPO thường ~1 giây
    - RTO thường dưới 1 phút
    - sao chép ở tầng lưu trữ
        ↓
    Nhưng đề nói "Amazon RDS for MySQL"
    → không phải Aurora

⚠ Và đây là điểm cần đọc kỹ trong đề:

"Amazon RDS for MySQL database"
        ↓
    Nếu đề nói Aurora
        ↓
    → Global Database là đáp án tốt
      nhất
        ↓
    Với RDS thường
    → cross-Region read replica là tốt
      nhất

⚠ Và vì sao phương án C kém hơn hẳn:

C dùng automated backup rồi thăng cấp
  backup thành instance
        ↓
    Thứ nhất: không "thăng cấp backup"
      được — phải KHÔI PHỤC
        ↓
    Thứ hai: khôi phục từ backup mất
      hàng chục phút tới hàng giờ
        ↓
    Thứ ba: mất dữ liệu từ lần backup
      cuối
    → RPO và RTO đều tệ hơn nhiều

Bảng RPO và RTO: | Cách | RPO | RTO | |---|---|---| | Aurora Global Database | ~1 giây | dưới 1 phút | | Cross-Region read replica | giây tới phút | vài phút | | Khôi phục từ backup | tới 5 phút (PITR) | chục phút tới giờ | | Snapshot sao chép | theo lịch chụp | giờ |

⚠ Và độ trễ sao chép phải được theo dõi:

aws cloudwatch put-metric-alarm \
  --alarm-name do-tre-sao-chep \
  --namespace AWS/RDS --metric-name ReplicaLag \
  --dimensions Name=DBInstanceIdentifier,Value=ban-sao-us-west \
  --statistic Maximum --period 300 \
  --threshold 300 --comparison-operator GreaterThanThreshold \
  --evaluation-periods 2 --alarm-actions <arn-sns>
Độ trễ tăng dần
        ↓
    RPO thực tế xấu hơn kỳ vọng
        ↓
    Thường do replica quá nhỏ hoặc
      băng thông liên Region không đủ

⚠ Và thăng cấp là thao tác MỘT CHIỀU:

Thăng cấp xong
        ↓
    Không quay lại làm replica được
        ↓
    Muốn trở về Region cũ
    → dựng replica ngược lại rồi thăng
      cấp lần nữa

⚠ Và ứng dụng phải đổi được endpoint:

Endpoint mới khác hoàn toàn
        ↓
    Ghi cứng trong mã → phải phát hành
      lại
        ↓
    → lưu endpoint trong Secrets
      Manager hoặc Parameter Store
    → đổi một chỗ, mọi nơi nhận
aws secretsmanager update-secret \
  --secret-id csdl/endpoint \
  --secret-string '{"host":"ban-sao-us-west.abc.us-west-2.rds.amazonaws.com","port":3306}'

⚠ Hoặc dùng CNAME trong Route 53 private hosted zone:

aws route53 change-resource-record-sets \
  --hosted-zone-id Z0123 \
  --change-batch '{"Changes": [{
    "Action": "UPSERT",
    "ResourceRecordSet": {
      "Name": "csdl.congty.local",
      "Type": "CNAME", "TTL": 60,
      "ResourceRecords": [{"Value":
        "ban-sao-us-west.abc.us-west-2.rds.amazonaws.com"}]}}]}'
Ứng dụng luôn dùng `csdl.congty.local`
        ↓
    Chuyển đổi = đổi một bản ghi CNAME
        ↓
    TTL 60 giây → lan nhanh

⚠ Và phải chuẩn bị sẵn mọi thứ ở Region dự phòng:

Không chỉ CSDL:
        ↓
    VPC, subnet, security group
        ↓
    Ứng dụng (AMI hoặc image container)
        ↓
    Secrets, tham số cấu hình
        ↓
    Chứng chỉ ACM (mỗi Region riêng)
    → thiếu một thứ là RTO tăng vọt

⚠ Và khoá KMS không dùng chung giữa các Region:

Replica ở Region khác cần khoá KMS
  của CHÍNH Region đó
        ↓
    Khai `--kms-key-id` khi tạo replica
        ↓
    Thiếu → lệnh thất bại

Ba lợi ích: | Lợi ích | Chi tiết | |---|---| | Dữ liệu luôn có ở Region thứ hai | | | Thăng cấp trong vài phút | | | Replica còn phục vụ đọc cho người dùng gần đó | |

⚠ Và diễn tập là bắt buộc:

Thăng cấp thử ở môi trường không phải
  sản xuất
        ↓
    Đo thời gian thật
        ↓
    Kiểm ứng dụng có kết nối được
      không
    → kế hoạch DR chưa diễn tập là kế
      hoạch chưa tồn tại

Vì sao các phương án khác sai

  • **C. Bật automated backup, khi có sự cố thì thăng cấp backup thành instance độc lập — đây là phương án gần nhất và backup thật sự là một lớp bảo vệ, nhưng không "thăng cấp backup" được mà phải khôi phục, việc đó mất hàng chục phút tới hàng giờ và mất dữ liệu từ điểm khôi phục.
  • **A. Bật global tables cho RDS — Global Tables là tính năng của DynamoDB, RDS không có.
  • **B. Bật multi-master cluster giữa nhiều Region — RDS for MySQL không có tính năng này; Aurora Multi-Master từng tồn tại nhưng chỉ trong một Region và đã ngừng phát triển.

Ghi nhớ

⚠ Bốn cơ chế DR liên Region — bảng phải thuộc: | Cơ chế | Dịch vụ | RTO | |---|---|---| | Aurora Global Database | Aurora | dưới 1 phút | | Cross-Region read replica | RDS, Aurora | vài phút | | DynamoDB Global Tables | DynamoDB | gần như 0 | | Khôi phục từ backup | mọi CSDL | giờ |

Từ khoá nhận diện:

"RDS for MySQL, multi-Region, highest availability" → cross-Region read replica "Aurora, multi-Region" → Global Database "global tables for RDS" → KHÔNG TỒN TẠI "promote a backup" → sai thuật ngữ, phải là khôi phục

Ba lưu ý về cross-Region replica: | Lưu ý | Chi tiết | |---|---| | Sao chép bất đồng bộ, có độ trễ | | | Thăng cấp là một chiều | | | Cần khoá KMS ở Region đích | |

Ba lưu ý về Aurora Global Database: | Lưu ý | Chi tiết | |---|---| | Sao chép ở tầng lưu trữ, RPO ~1 giây | | | Tối đa 5 Region phụ | | | Có managed failover | |

Ba lưu ý về endpoint: | Lưu ý | Chi tiết | |---|---| | Đừng ghi cứng trong mã | | | Lưu trong Secrets Manager hoặc Parameter Store | | | Hoặc dùng CNAME với TTL ngắn | |

Ba lưu ý về chuẩn bị Region dự phòng: | Lưu ý | Chi tiết | |---|---| | VPC, subnet, security group phải có sẵn | | | AMI và image container phải sao chép sang | | | Chứng chỉ ACM theo từng Region | |

Ba lưu ý về giám sát: | Metric | Ý nghĩa | |---|---| | ReplicaLag | RPO thực tế | | DatabaseConnections | tải trên replica | | FreeStorageSpace | replica có đủ chỗ không |

Ba lưu ý về chi phí: | Lưu ý | Chi tiết | |---|---| | Replica tính tiền như instance đầy đủ | | | Truyền dữ liệu liên Region tính phí | | | Cân nhắc instance nhỏ hơn cho replica DR | |

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Thăng cấp thử ở môi trường không sản xuất | | | Đo thời gian từ quyết định tới ứng dụng chạy lại | | | Kiểm ReplicaLag trong giờ cao điểm | |

Và một lời khuyên: hãy đọc kỹ đề nói RDS hay Aurora trước khi chọn giữa read replica và Global Database. Hai dịch vụ này có tên gần nhau và cùng chạy MySQL, nhưng cơ chế DR của chúng khác hẳn nhau — và Global Database chỉ tồn tại ở phía Aurora.

Câu 495 Chọn nhiều đáp án AWS Security, Identity, & Compliance

A company has deployed an eCommerce application that is used by thousands of customers to place online orders. The application runs on Amazon ECS tasks behind an Application Load Balancer (ALB) and data is stored in an Amazon DynamoDB table.

The application has recently experienced attacks that caused application slowdowns and outages. The company must prevent attacks and ensure business continuity with minimal service interruptions.

Which combination of steps will meet these requirements MOST cost-effectively? (Select TWO.)

  1. A

    Deploy the application in two AWS Regions. Configure Amazon Route 53 to route to both Regions with equal weight.

  2. B

    Create an Amazon CloudFront distribution with the ALB as the origin and configure a custom header and secret value. Configure the ALB to conditionally forward traffic only if the header and value match.

  3. C

    Configure AWS Auto Scaling for Amazon ECS tasks. Create an Amazon DynamoDB Accelerator (DAX) cluster in front of the DynamoDB table.

  4. D

    Deploy an AWS WAF web ACL that includes a rule group that blocks the attack traffic. Associate the web ACL with the Amazon CloudFront distribution.

  5. E

    Configure AWS Auto Scaling for Amazon ECS tasks. Configure an Amazon ElastiCache cluster in front of the DynamoDB table.

Xem giải thích

Đáp án

**B và D — Tạo một CloudFront distribution với ALB làm origin, cấu hình header tuỳ chỉnh kèm giá trị bí mật và bắt ALB chỉ chuyển tiếp khi header khớp; và triển khai một AWS WAF web ACL có rule group chặn lưu lượng tấn công, gắn vào CloudFront distribution.

Vì sao đúng

Hai mệnh đề này là hai nửa của cùng một giải pháp, và thiếu nửa nào cũng vô dụng.

⚠ Điểm mấu chốt: WAF chỉ có tác dụng nếu KHÔNG ai đi vòng được:

Gắn WAF vào CloudFront
        ↓
    Nhưng ALB vẫn có DNS công khai
        ↓
    Kẻ tấn công tìm ra DNS đó
        ↓
    Gọi thẳng, bỏ qua CloudFront và
      WAF
    → toàn bộ đầu tư vào WAF thành vô
      nghĩa
→ đó là lý do mệnh đề B tồn tại
→ và vì sao phải chọn CẢ HAI

Cấu hình header bí mật ở CloudFront:

{"Origins": {"Items": [{
   "Id": "alb-ung-dung",
   "DomainName": "alb-abc.ap-southeast-1.elb.amazonaws.com",
   "CustomOriginConfig": {
     "HTTPPort": 80, "HTTPSPort": 443,
     "OriginProtocolPolicy": "https-only"},
   "OriginCustomHeaders": {"Quantity": 1, "Items": [{
     "HeaderName": "X-Origin-Verify",
     "HeaderValue": "<chuoi-bi-mat-dai>"}]}}]}}

Luật ở ALB kiểm header:

aws elbv2 create-rule --listener-arn <arn-listener> \
  --priority 1 \
  --conditions '[{"Field": "http-header",
    "HttpHeaderConfig": {
      "HttpHeaderName": "X-Origin-Verify",
      "Values": ["<chuoi-bi-mat-dai>"]}}]' \
  --actions Type=forward,TargetGroupArn=<arn-tg>

aws elbv2 modify-listener --listener-arn <arn-listener> \
  --default-actions '[{"Type": "fixed-response",
    "FixedResponseConfig": {"StatusCode": "403",
      "ContentType": "text/plain",
      "MessageBody": "Truy cap bi tu choi"}}]'

⚠ Và luật mặc định phải trả 403 — nếu không thì vô tác dụng:

Chỉ thêm luật cho phép khi có header
        ↓
    Nhưng luật mặc định vẫn chuyển
      tiếp
        ↓
    Yêu cầu không có header vẫn đi qua
    → phải đổi cả hành động mặc định

⚠ Và giá trị bí mật phải được xoay vòng:

aws secretsmanager rotate-secret \
  --secret-id cloudfront/origin-header \
  --rotation-lambda-arn <arn-lambda> \
  --rotation-rules AutomaticallyAfterDays=30
Header lộ ra qua log hoặc qua người
  nghỉ việc
        ↓
    → kẻ tấn công đi vòng được lần nữa
        ↓
    Xoay vòng: cập nhật CloudFront và
      ALB gần như đồng thời
    → cho phép hai giá trị trong thời
      gian chuyển tiếp

⚠ Và VPC origin là cách chặt hơn, không cần bí mật:

CloudFront VPC origin kết nối riêng
  tư tới ALB NỘI BỘ
        ↓
    ALB không có địa chỉ công khai nào
        ↓
    → không có đường đi vòng nào tồn
      tại
    → chặt hơn header bí mật

Cấu hình WAF:

aws wafv2 create-web-acl \
  --name bao-ve-ung-dung --scope CLOUDFRONT \
  --region us-east-1 \
  --default-action Allow={} \
  --visibility-config SampledRequestsEnabled=true,\
CloudWatchMetricsEnabled=true,MetricName=baoVeUngDung \
  --rules file://luat.json

⚠ Và --scope CLOUDFRONT phải tạo ở us-east-1:

Web ACL cho CloudFront là tài nguyên
  toàn cục
        ↓
    Chỉ tạo được ở `us-east-1`
        ↓
    Tạo ở Region khác → lỗi
    → đây là chi tiết hay vấp

Ba nhóm luật quản lý nên bật:

{"Rules": [
  {"Name": "ChanFlood", "Priority": 1,
   "Statement": {"RateBasedStatement": {
     "Limit": 2000, "AggregateKeyType": "IP"}},
   "Action": {"Block": {}},
   "VisibilityConfig": {"SampledRequestsEnabled": true,
     "CloudWatchMetricsEnabled": true, "MetricName": "chanFlood"}},
  {"Name": "LuatChung", "Priority": 2,
   "Statement": {"ManagedRuleGroupStatement": {
     "VendorName": "AWS",
     "Name": "AWSManagedRulesCommonRuleSet"}},
   "OverrideAction": {"None": {}},
   "VisibilityConfig": {"SampledRequestsEnabled": true,
     "CloudWatchMetricsEnabled": true, "MetricName": "luatChung"}},
  {"Name": "DauVaoXau", "Priority": 3,
   "Statement": {"ManagedRuleGroupStatement": {
     "VendorName": "AWS",
     "Name": "AWSManagedRulesKnownBadInputsRuleSet"}},
   "OverrideAction": {"None": {}},
   "VisibilityConfig": {"SampledRequestsEnabled": true,
     "CloudWatchMetricsEnabled": true, "MetricName": "dauVaoXau"}}]}

⚠ Và luôn chạy ở chế độ Count trước khi Block:

{"OverrideAction": {"Count": {}}}
Nhóm luật quản lý có thể chặn nhầm
  lưu lượng thật
        ↓
    Chạy Count vài ngày
        ↓
    Xem `SampledRequests` xem chặn cái
      gì
    → rồi mới chuyển sang Block

⚠ Và rate-based rule là thứ chống DDoS tầng 7:

Đề nói "tấn công làm chậm và ngừng
  dịch vụ"
        ↓
    Đó là mô tả của HTTP flood
        ↓
    Rate-based rule đếm yêu cầu mỗi IP
      trong 5 phút
    → vượt ngưỡng thì chặn tạm

⚠ Và CloudFront có Shield Standard miễn phí:

Chống DDoS tầng 3/4 tự động
        ↓
    Bật sẵn cho mọi distribution
        ↓
    Cộng với WAF chống tầng 7
    → hai tầng bảo vệ

⚠ Và vì sao phương án A không hiệu quả về chi phí:

A triển khai ứng dụng ở HAI Region
        ↓
    Nhân đôi chi phí tính toán, CSDL,
      vận hành
        ↓
    Và không chặn được tấn công
        ↓
    Chỉ chia tải tấn công ra hai nơi
    → đề hỏi cách "hiệu quả chi phí
      NHẤT"

⚠ Và vì sao phương án C và E không giải quyết đúng vấn đề:

C và E dùng Auto Scaling + DAX hoặc
  ElastiCache
        ↓
    Đó là cách CHỊU ĐỰNG tấn công
        ↓
    Co giãn để phục vụ cả lưu lượng
      độc hại
        ↓
    → trả tiền cho chính cuộc tấn công
    → đề nói "NGĂN CHẶN tấn công"

⚠ Và co giãn theo tấn công là bẫy chi phí:

Kẻ tấn công gửi 100.000 yêu cầu/giây
        ↓
    ASG tăng lên hàng trăm task
        ↓
    Hoá đơn tăng vọt
        ↓
    Đây gọi là "denial of wallet"
    → chặn ở biên rẻ hơn nhiều

⚠ Và DAX cũng không đúng chỗ:

E dùng ElastiCache trước DynamoDB
        ↓
    DynamoDB đã có DAX chuyên dụng
        ↓
    Và đề không nói CSDL là điểm nghẽn
    → chữa triệu chứng không tồn tại

⚠ Và CloudFront còn giảm tải nhờ cache:

Nội dung tĩnh cache ở biên
        ↓
    Không chạm tới ECS
        ↓
    Ngay cả lưu lượng bình thường cũng
      giảm
    → tiết kiệm ngoài việc bảo vệ

⚠ Và nên bật WAF logging để điều tra:

aws wafv2 put-logging-configuration --logging-configuration '{
  "ResourceArn": "<arn-web-acl>",
  "LogDestinationConfigs": ["<arn-firehose>"],
  "RedactedFields": [{"SingleHeader": {"Name": "authorization"}}]}'

⚠ Và tên luồng Firehose phải bắt đầu bằng aws-waf-logs-:

Sai tiền tố
        ↓
    Không chọn được luồng
    → và thông báo lỗi không nói rõ lý
      do

Ba lợi ích của tổ hợp: | Lợi ích | Chi tiết | |---|---| | Chặn tấn công ở biên, không tới ứng dụng | | | Không có đường đi vòng | | | Rẻ hơn nhiều so với nhân đôi hạ tầng | |

⚠ Và Shield Advanced đáng cân nhắc nếu bị tấn công thường xuyên:

3.000 USD/tháng
        ↓
    Có đội phản ứng của AWS
        ↓
    Bảo vệ chi phí khi co giãn vì tấn
      công
    → khoản cuối này thường là lý do
      chính

Vì sao các phương án khác sai

  • **A. Triển khai ứng dụng ở hai Region và cân bằng bằng Route 53 trọng số bằng nhau — đây là phương án gần nhất về mặt "tăng khả năng chịu đựng", nhưng nó nhân đôi chi phí mà không chặn được cuộc tấn công nào; lưu lượng độc hại chỉ được chia ra hai nơi.
  • **C. Auto Scaling cho ECS + cụm DAX trước DynamoDB — co giãn để phục vụ cả lưu lượng tấn công, biến vấn đề bảo mật thành hoá đơn tăng vọt.
  • **E. Auto Scaling cho ECS + ElastiCache trước DynamoDB — cùng vấn đề, và DynamoDB đã có DAX chuyên dụng nên ElastiCache là lựa chọn kém phù hợp hơn.

Ghi nhớ

⚠ Bốn lớp chống tấn công web — bảng phải thuộc: | Lớp | Chặn gì | |---|---| | Shield Standard | DDoS tầng 3/4, miễn phí | | WAF | HTTP flood, SQLi, XSS, bot | | Header bí mật hoặc VPC origin | đường đi vòng qua ALB | | Shield Advanced | DDoS lớn + bảo vệ chi phí |

Từ khoá nhận diện:

"prevent attacks cost-effectively" → CloudFront + WAF "bypass the WAF" → header bí mật hoặc VPC origin "scale to absorb attack" → bẫy chi phí, không phải giải pháp "multi-Region for attacks" → nhân đôi chi phí, không chặn gì

Ba lưu ý về WAF: | Lưu ý | Chi tiết | |---|---| | Scope CLOUDFRONT phải tạo ở us-east-1 | | | Chạy Count trước khi Block | | | Rate-based rule chống HTTP flood | |

Ba lưu ý về bảo vệ origin: | Cách | Mức chặt | |---|---| | Header bí mật | tốt, cần xoay vòng | | Dải IP CloudFront trong SG | tốt, kết hợp với header | | VPC origin | chặt nhất |

Ba lưu ý về nhóm luật quản lý: | Nhóm | Chặn | |---|---| | CommonRuleSet | tấn công phổ biến | | KnownBadInputsRuleSet | payload đã biết là xấu | | IpReputationList | IP có tiếng xấu |

Ba lưu ý về chi phí: | Lưu ý | Chi tiết | |---|---| | Chặn ở biên rẻ hơn co giãn | | | CloudFront giảm cả lưu lượng bình thường | | | Shield Advanced có bảo vệ chi phí | |

Ba lưu ý về giám sát: | Lưu ý | Chi tiết | |---|---| | Bật WAF logging qua Firehose | | | Xem SampledRequests để tinh chỉnh luật | | | Cảnh báo BlockedRequests tăng đột ngột | |

Ba lưu ý về xoay vòng bí mật: | Lưu ý | Chi tiết | |---|---| | Cho phép hai giá trị trong lúc chuyển | | | Cập nhật CloudFront trước, ALB sau | | | Tự động hoá bằng Secrets Manager | |

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Gọi thẳng DNS của ALB — phải bị 403 | | | Gửi payload SQLi — WAF phải chặn | | | Kiểm BlockedRequests trong CloudWatch | |

Và một lời khuyên: hãy thử gọi thẳng DNS của ALB sau khi dựng xong và xác nhận nhận được 403. Đây là bước kiểm chứng mà rất nhiều đội bỏ qua — và nếu ALB vẫn trả lời, thì mọi luật WAF bạn vừa cấu hình chỉ là trang trí cho một cánh cửa vẫn mở toang bên cạnh.

Câu 496 AWS Database

A company is designing an application that will requires cross-Region disaster recovery with an RTO of less than 5 minutes and an RPO of less than 1 minute. The application tier DR solution has already been designed and a Solutions Architect must design the data recovery solution for the MySQL database tier.

How should the database tier be configured to meet the data recovery requirements?

  1. A

    Create an Amazon RDS instance in the active Region and use a MySQL standby database on an Amazon EC2 instance in the failover Region.

  2. B

    Use an Amazon RDS for MySQL instance with a Multi-AZ deployment.

  3. C

    Use an Amazon RDS for MySQL instance with a cross-Region read replica in the failover Region.

  4. D

    Use an Amazon Aurora global database with the primary in the active Region and the secondary in the failover Region.

Xem giải thích

Đáp án

**D — Dùng Amazon Aurora Global Database với cụm chính ở Region đang hoạt động và cụm phụ ở Region dự phòng.

Vì sao đúng

Đề đưa ra hai con số cụ thể, và chúng loại gần hết các phương án: | Yêu cầu | Con số | |---|---| | RTO | dưới 5 phút | | RPO | dưới 1 phút |

⚠ Điểm mấu chốt: Aurora Global Database là lựa chọn duy nhất đạt cả hai: | Cách | RPO điển hình | RTO điển hình | |---|---|---| | Aurora Global Database | ~1 giây | dưới 1 phút (managed failover) | | Cross-Region read replica | giây tới phút | vài phút | | Multi-AZ | 0 nhưng KHÔNG liên Region | 60-120 giây | | Standby tự dựng trên EC2 | tuỳ cấu hình | thường rất lâu |

⚠ Và Aurora Global Database sao chép ở tầng LƯU TRỮ:

Không dùng replication của engine
      MySQL
        ↓
    Lớp lưu trữ của Aurora tự sao chép
      sang Region khác
        ↓
    Độ trễ thường dưới 1 giây
        ↓
    Và không tốn CPU của instance
      chính
    → khác hẳn binlog replication

Dựng global cluster:

aws rds create-global-cluster \
  --global-cluster-identifier cum-toan-cau \
  --source-db-cluster-identifier <arn-cum-chinh>

aws rds create-db-cluster \
  --db-cluster-identifier cum-phu-us-west \
  --engine aurora-mysql \
  --global-cluster-identifier cum-toan-cau \
  --region us-west-2

aws rds create-db-instance \
  --db-instance-identifier cum-phu-us-west-1 \
  --db-cluster-identifier cum-phu-us-west \
  --engine aurora-mysql --db-instance-class db.r6g.large \
  --region us-west-2

⚠ Và có hai kiểu chuyển đổi — phải phân biệt: | Kiểu | Dùng khi | RTO | |---|---|---| | Managed planned failover | Region chính vẫn khoẻ (diễn tập, bảo trì) | dưới 1 phút, RPO = 0 | | Failover thủ công (detach & promote) | Region chính đã mất | vài phút |

Chuyển đổi có kế hoạch:

aws rds failover-global-cluster \
  --global-cluster-identifier cum-toan-cau \
  --target-db-cluster-identifier <arn-cum-phu>
Đồng bộ hai bên trước khi chuyển
        ↓
    RPO = 0
        ↓
    Nhưng chỉ dùng được khi Region
      chính còn sống

Chuyển đổi khi thảm hoạ thật:

aws rds remove-from-global-cluster \
  --global-cluster-identifier cum-toan-cau \
  --db-cluster-identifier <arn-cum-phu> \
  --region us-west-2
Tách cụm phụ ra
        ↓
    Nó thành cụm độc lập, ghi được
        ↓
    Mất phần dữ liệu chưa kịp sao chép
    → đó là RPO ~1 giây

⚠ Và headless secondary cluster tiết kiệm chi phí:

Cụm phụ không cần instance nào cả
        ↓
    Lớp lưu trữ vẫn sao chép
        ↓
    Chỉ trả tiền lưu trữ và I/O
        ↓
    Khi cần → khởi chạy instance
    → nhưng RTO tăng thêm vài phút
Đề đòi RTO dưới 5 phút
        ↓
    → nên giữ ít nhất một instance ở
      cụm phụ
    → hoặc đo kỹ thời gian khởi chạy

⚠ Và vì sao phương án C không đạt RTO:

C dùng cross-Region read replica của
  RDS for MySQL
        ↓
    Thăng cấp mất vài phút
        ↓
    Và độ trễ sao chép qua binlog
      thường cao hơn Aurora
        ↓
    Có thể đạt được, nhưng sát ngưỡng
    → Aurora Global Database an toàn
      hơn hẳn

⚠ Và binlog replication chịu tải khác hẳn tầng lưu trữ:

RDS MySQL replica đọc binlog
        ↓
    Áp lại từng câu lệnh
        ↓
    Ghi nhiều → replica tụt lại
        ↓
    Aurora sao chép khối lưu trữ
    → không phụ thuộc tốc độ áp lệnh

⚠ Và vì sao phương án B sai hoàn toàn:

B dùng RDS for MySQL Multi-AZ
        ↓
    Multi-AZ là TRONG MỘT REGION
        ↓
    Đề đòi khôi phục LIÊN REGION
        ↓
    Region mất → cả hai AZ mất
    → không đáp ứng yêu cầu cơ bản

⚠ Và vì sao phương án A tệ nhất:

A dùng RDS ở Region chính và MySQL
  standby TỰ DỰNG trên EC2 ở Region
  kia
        ↓
    Phải tự cấu hình replication
        ↓
    Tự giám sát, tự chuyển đổi
        ↓
    Tự vá lỗi, tự sao lưu
    → và RDS không hỗ trợ replica
      ngoài AWS theo cách này dễ dàng

⚠ Và Aurora Global Database còn có write forwarding:

aws rds modify-db-cluster \
  --db-cluster-identifier cum-phu-us-west \
  --enable-global-write-forwarding \
  --region us-west-2
Ứng dụng ở Region phụ ghi vào cụm phụ
        ↓
    Aurora chuyển tiếp lệnh ghi về cụm
      chính
        ↓
    Ứng dụng không phải biết Region
      nào là chính
    → nhưng có thêm độ trễ cho lệnh
      ghi

⚠ Và tối đa 5 Region phụ:

Một cụm chính
        ↓
    Tối đa 5 cụm phụ ở 5 Region
        ↓
    Mỗi cụm phụ có tối đa 16 reader
    → phục vụ đọc toàn cầu

⚠ Và theo dõi RPO thực tế bằng metric:

aws cloudwatch get-metric-statistics \
  --namespace AWS/RDS \
  --metric-name AuroraGlobalDBRPOLag \
  --dimensions Name=DBClusterIdentifier,Value=cum-phu-us-west \
  --statistics Maximum --period 60 \
  --start-time 2026-09-01T00:00:00Z \
  --end-time 2026-09-01T12:00:00Z \
  --region us-west-2

Ba metric quan trọng: | Metric | Ý nghĩa | |---|---| | AuroraGlobalDBRPOLag | RPO thực tế tính bằng mili giây | | AuroraGlobalDBReplicationLag | độ trễ sao chép | | AuroraGlobalDBDataTransferBytes | lượng dữ liệu sao chép |

⚠ Và có thể đặt trần RPO để tự bảo vệ:

aws rds modify-db-cluster \
  --db-cluster-identifier cum-chinh \
  --db-cluster-parameter-group-name nhom-tham-so \
  --region ap-southeast-1
Tham số `rds.global_db_rpo`
        ↓
    Đặt trần RPO tính bằng giây
        ↓
    Vượt trần → Aurora CHẶN lệnh ghi
      mới
    → bảo đảm RPO nhưng đánh đổi tính
      sẵn sàng

⚠ Và ứng dụng phải đổi được endpoint nhanh:

Endpoint cụm phụ khác cụm chính
        ↓
    Lưu trong Secrets Manager hoặc
      Parameter Store
        ↓
    Hoặc dùng Route 53 với health check
    → RTO không chỉ là thời gian của
      CSDL

⚠ Và RTO tổng gồm nhiều phần:

Phát hiện sự cố          (1-2 phút)
        ↓
Quyết định chuyển đổi    (vài chục giây)
        ↓
Tách và thăng cấp cụm    (dưới 1 phút)
        ↓
Đổi endpoint, lan DNS    (1-2 phút)
        ↓
Ứng dụng kết nối lại     (vài chục giây)
    → tổng phải dưới 5 phút

⚠ Và tự động hoá phát hiện là phần khó nhất:

Chuyển đổi tự động khi Region mất
        ↓
    Rủi ro: chuyển nhầm khi chỉ là sự
      cố mạng tạm
        ↓
    Chuyển đổi thủ công
    → an toàn hơn nhưng chậm hơn
    → phần lớn tổ chức chọn thủ công
      có quy trình sẵn

Ba lợi ích: | Lợi ích | Chi tiết | |---|---| | RPO ~1 giây, RTO dưới 1 phút | | | Không tốn CPU cụm chính để sao chép | | | Cụm phụ phục vụ đọc cho người dùng gần đó | |

Vì sao các phương án khác sai

  • **C. RDS for MySQL với cross-Region read replica — đây là phương án gần nhất và thật sự là cơ chế DR liên Region hợp lệ, nhưng sao chép qua binlog có độ trễ cao hơn và biến động hơn, còn thăng cấp mất vài phút; với RPO dưới 1 phút và RTO dưới 5 phút thì nó nằm sát ngưỡng chứ không an toàn.
  • **B. RDS for MySQL Multi-AZ — Multi-AZ hoạt động trong một Region, không đáp ứng yêu cầu khôi phục liên Region.
  • **A. RDS ở Region chính + MySQL standby tự dựng trên EC2 ở Region dự phòng — phải tự cấu hình, tự giám sát và tự chuyển đổi; RTO và RPO đều không đảm bảo được.

Ghi nhớ

⚠ Bốn cơ chế và con số RPO/RTO — bảng phải thuộc: | Cơ chế | RPO | RTO | |---|---|---| | Aurora Global Database | ~1 giây | dưới 1 phút | | Cross-Region read replica | giây tới phút | vài phút | | Multi-AZ | 0, cùng Region | 60-120 giây | | Khôi phục backup | tới 5 phút | giờ |

Từ khoá nhận diện:

"cross-Region, RTO < 5 min, RPO < 1 min" → Aurora Global Database "Multi-AZ for DR" → SAI, cùng Region "self-managed standby on EC2" → luôn kém hơn dịch vụ quản lý "RPO must be guaranteed" → tham số rds.global_db_rpo

Ba lưu ý về Aurora Global Database: | Lưu ý | Chi tiết | |---|---| | Sao chép ở tầng lưu trữ | | | Tối đa 5 Region phụ | | | Có managed planned failover với RPO = 0 | |

Ba lưu ý về chuyển đổi: | Kiểu | Khi nào | |---|---| | failover-global-cluster | Region chính còn sống | | remove-from-global-cluster | Region chính đã mất | | Không quay lại tự động | phải dựng lại quan hệ |

Ba lưu ý về chi phí: | Lưu ý | Chi tiết | |---|---| | Headless secondary rẻ nhất nhưng RTO cao hơn | | | Truyền dữ liệu liên Region tính phí | | | Cụm phụ phục vụ đọc thì không lãng phí | |

Ba metric phải theo dõi: | Metric | Ý nghĩa | |---|---| | AuroraGlobalDBRPOLag | RPO thực tế | | AuroraGlobalDBReplicationLag | độ trễ sao chép | | AuroraGlobalDBProgressLag | tiến độ áp dữ liệu |

Ba lưu ý về RTO tổng: | Phần | Thời gian | |---|---| | Phát hiện | 1-2 phút | | Chuyển đổi CSDL | dưới 1 phút | | Đổi endpoint và lan DNS | 1-2 phút |

Ba lưu ý về write forwarding: | Lưu ý | Chi tiết | |---|---| | Ứng dụng ở Region phụ ghi được | | | Lệnh ghi chuyển về cụm chính | | | Có thêm độ trễ cho ghi | |

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Chạy managed failover định kỳ | | | Đo AuroraGlobalDBRPOLag lúc tải cao | | | Bấm giờ toàn bộ quy trình chuyển đổi | |

Và một lời khuyên: hãy bấm giờ toàn bộ quy trình chứ đừng chỉ tính thời gian chuyển đổi của cơ sở dữ liệu. RTO dưới 5 phút là ràng buộc về mặt hệ thống, và phần lớn thời gian thực tế nằm ở việc phát hiện sự cố, ra quyết định và chờ DNS lan — chứ không phải ở một phút Aurora thăng cấp cụm phụ.

Câu 497 Chọn nhiều đáp án AWS Database

A company has deployed an application that uses an Amazon DynamoDB table and the user base has increased significantly. Users have reported poor response times during busy periods but no error pages have been generated. The application uses Amazon DynamoDB in read-only mode. The operations team has determined that the issue relates to ProvisionedThroughputExceeded exceptions in the application logs when doing Scan and read operations.
A Solutions Architect has been tasked with improving application performance. Which solutions will meet these requirements whilst MINIMIZING changes to the application? (Select TWO.)

  1. A

    Provision an Amazon ElastiCache for Redis cluster. The cluster should be provisioned with enough shards to handle the peak application load.

  2. B

    Include error retries and exponential backoffs in the application code to handle throttling errors and reduce load during periods of high requests.

  3. C

    Enable DynamoDB Auto Scaling to manage the throughput capacity as table traffic increases. Set the upper and lower limits to control costs and set a target utilization based on the peak usage.

  4. D

    Enable adaptive capacity for the DynamoDB table to minimize throttling due to throughput exceptions.

  5. E

    Provision a DynamoDB Accelerator (DAX) cluster with the correct number and type of nodes. Tune the item and query cache configuration for an optimal user experience.

Xem giải thích

Đáp án

**C và E — Bật DynamoDB Auto Scaling để quản công suất khi lưu lượng tăng, đặt trần trên và trần dưới cùng mức sử dụng mục tiêu theo đỉnh tải; và dựng một cụm DynamoDB Accelerator (DAX) với số lượng và loại node phù hợp, tinh chỉnh cấu hình cache mục và cache truy vấn.

Vì sao đúng

Đề nêu ba manh mối quyết định: | Manh mối | Ý nghĩa | |---|---| | ProvisionedThroughputExceeded | bảng đang ở chế độ provisioned và thiếu công suất | | Ứng dụng chỉ ĐỌC | cache là lựa chọn tự nhiên | | Ít thay đổi mã nhất | DAX dùng API tương thích DynamoDB |

⚠ Điểm mấu chốt: DAX là cache DUY NHẤT không cần sửa logic ứng dụng:

Client DAX có API tương thích DynamoDB
        ↓
    Chỉ đổi client và endpoint
        ↓
    `get_item`, `query`, `scan` giữ
      nguyên
    → không phải viết logic cache nào
# Trước
import boto3
bang = boto3.resource('dynamodb').Table('du-lieu')

# Sau
from amazondax import AmazonDaxClient
dax = AmazonDaxClient.resource(
    endpoint_url='dax://cum-dax.abc.dax-clusters.ap-southeast-1.amazonaws.com')
bang = dax.Table('du-lieu')

⚠ Và đó là lý do phương án A kém hơn:

A dùng ElastiCache for Redis
        ↓
    Phải tự viết:
      - kiểm cache trước
      - gọi DynamoDB khi miss
      - ghi kết quả vào cache
      - đặt TTL
      - xử lý vô hiệu hoá cache
        ↓
    Đề nói "ít thay đổi ứng dụng nhất"
    → DAX thắng rõ ràng

Bảng so sánh: | | DAX | ElastiCache | |---|---|---| | Thay đổi mã | đổi client | viết toàn bộ logic cache | | Vô hiệu hoá cache | tự động khi ghi qua DAX | tự lo | | Chỉ dùng với | DynamoDB | mọi nguồn | | Độ trễ | micro giây | mili giây |

Dựng cụm DAX:

aws dax create-cluster \
  --cluster-name cum-dax \
  --node-type dax.r5.large \
  --replication-factor 3 \
  --iam-role-arn <arn-role> \
  --subnet-group-name nhom-subnet-dax \
  --security-group-ids sg-dax \
  --sse-specification Enabled=true

⚠ Và replication-factor là số node, tối thiểu 3 cho sản xuất:

1 node → không có sẵn sàng cao
        ↓
    3 node → một node chính, hai bản
      sao ở AZ khác
        ↓
    Node chính hỏng → tự thăng cấp

⚠ Và DAX có HAI cache riêng biệt — đây là phần "tinh chỉnh" trong đáp án: | Cache | Chứa gì | TTL mặc định | |---|---|---| | Item cache | kết quả GetItem, BatchGetItem | 5 phút | | Query cache | kết quả Query, Scan | 5 phút |

aws dax create-parameter-group \
  --parameter-group-name tham-so-dax \
  --description "TTL tuy chinh"

aws dax update-parameter-group \
  --parameter-group-name tham-so-dax \
  --parameter-name-values \
    ParameterName=record-ttl-millis,ParameterValue=600000 \
    ParameterName=query-ttl-millis,ParameterValue=60000

⚠ Và query cache KHÔNG tự vô hiệu hoá khi dữ liệu đổi:

Ghi một mục qua DAX
        ↓
    Item cache của mục đó được cập
      nhật
        ↓
    Nhưng query cache thì KHÔNG
        ↓
    → truy vấn cũ vẫn trả kết quả cũ
      tới hết TTL
    → đặt query TTL ngắn hơn item TTL

⚠ Và ứng dụng ở đây chỉ đọc nên vấn đề đó nhẹ:

Đề nói "uses DynamoDB in read-only
  mode"
        ↓
    Không có lệnh ghi nào
        ↓
    Dữ liệu đổi từ nguồn khác
    → vẫn phải cân nhắc TTL

⚠ Điểm mấu chốt thứ hai: Auto Scaling chữa nguyên nhân gốc:

aws application-autoscaling register-scalable-target \
  --service-namespace dynamodb \
  --resource-id table/du-lieu \
  --scalable-dimension dynamodb:table:ReadCapacityUnits \
  --min-capacity 100 --max-capacity 4000

aws application-autoscaling put-scaling-policy \
  --service-namespace dynamodb \
  --resource-id table/du-lieu \
  --scalable-dimension dynamodb:table:ReadCapacityUnits \
  --policy-name chinh-sach-doc \
  --policy-type TargetTrackingScaling \
  --target-tracking-scaling-policy-configuration '{
    "TargetValue": 70.0,
    "ScaleInCooldown": 300,
    "ScaleOutCooldown": 60,
    "PredefinedMetricSpecification": {
      "PredefinedMetricType": "DynamoDBReadCapacityUtilization"}}'

⚠ Và phải đặt Auto Scaling cho CẢ chỉ mục phụ toàn cục:

aws application-autoscaling register-scalable-target \
  --service-namespace dynamodb \
  --resource-id table/du-lieu/index/chi-muc-1 \
  --scalable-dimension dynamodb:index:ReadCapacityUnits \
  --min-capacity 50 --max-capacity 2000
GSI có công suất RIÊNG
        ↓
    Chỉ co giãn bảng chính
        ↓
    GSI vẫn throttle
    → và lỗi trông giống hệt nhau

⚠ Và vì sao mệnh đề D sai — adaptive capacity KHÔNG bật được:

D nói "bật adaptive capacity"
        ↓
    Adaptive capacity LUÔN BẬT từ 2019
        ↓
    Không có công tắc nào cả
        ↓
    → mệnh đề mô tả một thao tác không
      tồn tại

⚠ Và adaptive capacity làm gì:

Phân bổ lại công suất giữa các phân
  vùng
        ↓
    Phân vùng nóng mượn công suất từ
      phân vùng nguội
        ↓
    Tự động, tức thì
        ↓
    Nhưng chỉ giúp khi tổng công suất
      ĐỦ
    → không giúp khi cả bảng thiếu
      công suất

⚠ Và vì sao mệnh đề B không phải giải pháp:

B thêm retry và exponential backoff
        ↓
    Đó là thực hành TỐT và nên có
        ↓
    Nhưng nó không thêm công suất nào
        ↓
    Người dùng vẫn chờ lâu
    → và đề nói "phản hồi chậm", đúng
      triệu chứng của việc thử lại
Và SDK của AWS đã có retry với
  exponential backoff MẶC ĐỊNH
        ↓
    Đó chính là lý do người dùng thấy
      CHẬM chứ không thấy LỖI
    → đề nói "không có trang lỗi nào"

⚠ Và đây là chi tiết tinh tế của đề:

"Poor response times but no error
  pages"
        ↓
    Nghĩa là SDK đang tự thử lại
        ↓
    Throttle bị nuốt thành độ trễ
    → thêm retry nữa chỉ làm chậm hơn

⚠ Và Scan là thủ phạm rất có thể:

Đề nói "Scan and read operations"
        ↓
    `Scan` đọc TOÀN BỘ bảng
        ↓
    Tốn đơn vị đọc theo kích thước
      bảng, không theo kết quả
        ↓
    → nên chuyển sang `Query` nếu được
    → hoặc thêm GSI phù hợp

⚠ Và DAX cache được Scan — điều này giúp rất nhiều:

`Scan` giống nhau lặp lại
        ↓
    Query cache trả ngay
        ↓
    Không tốn đơn vị đọc nào
    → đây là nơi DAX có giá trị lớn
      nhất trong ca này

⚠ Và eventually consistent read rẻ hơn một nửa:

Strongly consistent: 1 RCU mỗi 4 KB
        ↓
    Eventually consistent: 0,5 RCU mỗi
      4 KB
        ↓
    Ứng dụng chịu được độ trễ nhỏ
    → giảm nửa chi phí đọc
Và DAX chỉ cache eventually
  consistent read
        ↓
    Yêu cầu strongly consistent đi
      thẳng tới DynamoDB
    → không hưởng lợi từ cache

⚠ Và nên cân nhắc chuyển sang on-demand:

aws dynamodb update-table --table-name du-lieu \
  --billing-mode PAY_PER_REQUEST
Không bao giờ throttle vì đoán sai
        ↓
    Nhưng đắt hơn ~6 lần mỗi đơn vị
        ↓
    Tải tăng đều và dự đoán được
    → Auto Scaling rẻ hơn

⚠ Và theo dõi đúng metric:

aws cloudwatch get-metric-statistics \
  --namespace AWS/DynamoDB \
  --metric-name ThrottledRequests \
  --dimensions Name=TableName,Value=du-lieu \
  --statistics Sum --period 300 \
  --start-time 2026-09-01T00:00:00Z \
  --end-time 2026-09-01T12:00:00Z

Ba metric quan trọng: | Metric | Ý nghĩa | |---|---| | ThrottledRequests | có bị chặn không | | ConsumedReadCapacityUnits | dùng bao nhiêu | | ProvisionedReadCapacityUnits | cấp bao nhiêu |

Và metric của DAX: | Metric | Ý nghĩa | |---|---| | ItemCacheHits / ItemCacheMisses | hiệu quả item cache | | QueryCacheHits / QueryCacheMisses | hiệu quả query cache | | CPUUtilization | node DAX có quá tải không |

Ba lợi ích: | Lợi ích | Chi tiết | |---|---| | Không phải viết logic cache | | | Độ trễ xuống micro giây khi cache hit | | | Công suất tự tăng khi tải tăng | |

⚠ Và DAX phải nằm trong VPC:

DAX chỉ truy cập được từ trong VPC
        ↓
    Ứng dụng ngoài VPC không gọi được
        ↓
    Lambda phải đặt trong VPC
    → và khi đó cần endpoint cho các
      dịch vụ khác

Vì sao các phương án khác sai

  • **A. Dựng cụm ElastiCache for Redis với đủ shard cho đỉnh tải — đây là phương án gần nhất và thật sự giảm được tải đọc, nhưng phải tự viết toàn bộ logic kiểm cache, ghi cache và vô hiệu hoá cache, trái với yêu cầu "ít thay đổi ứng dụng nhất".
  • **B. Thêm retry và exponential backoff — SDK của AWS đã làm sẵn việc này, và đó chính là lý do triệu chứng hiện ra là chậm chứ không phải lỗi; thêm nữa không tạo ra công suất nào.
  • **D. Bật adaptive capacity — tính năng này luôn bật từ năm 2019, không có thao tác nào để bật.

Ghi nhớ

⚠ Bốn cách chữa ProvisionedThroughputExceeded — bảng phải thuộc: | Cách | Tác dụng | |---|---| | Auto Scaling | tăng công suất theo tải | | On-demand | không bao giờ throttle, đắt hơn | | DAX | giảm số lượt đọc chạm bảng | | Đổi Scan thành Query | giảm đơn vị đọc rất nhiều |

Từ khoá nhận diện:

"minimal application changes + DynamoDB cache" → DAX "enable adaptive capacity" → LUÔN SAI, đã bật sẵn "slow but no errors" → SDK đang tự thử lại throttle "cache any data source" → ElastiCache

Ba lưu ý về DAX: | Lưu ý | Chi tiết | |---|---| | API tương thích DynamoDB | | | Chỉ cache eventually consistent read | | | Phải nằm trong VPC | |

Hai cache của DAX: | Cache | Vô hiệu hoá khi ghi | |---|---| | Item cache | có (nếu ghi qua DAX) | | Query cache | KHÔNG |

Ba lưu ý về Auto Scaling: | Lưu ý | Chi tiết | |---|---| | Phải đặt cho cả GSI | | | Mục tiêu 70% là hợp lý | | | Scale-out cooldown ngắn hơn scale-in | |

Ba lưu ý về đơn vị đọc: | Loại | Chi phí | |---|---| | Strongly consistent | 1 RCU / 4 KB | | Eventually consistent | 0,5 RCU / 4 KB | | Transactional | 2 RCU / 4 KB |

Ba lưu ý về Scan: | Lưu ý | Chi tiết | |---|---| | Đọc toàn bộ bảng | | | Tốn theo kích thước bảng, không theo kết quả | | | Thêm GSI để chuyển sang Query | |

Ba lưu ý về adaptive capacity: | Lưu ý | Chi tiết | |---|---| | Luôn bật, không có công tắc | | | Phân bổ lại giữa các phân vùng | | | Không giúp khi tổng công suất thiếu | |

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Xem ThrottledRequests về 0 chưa | | | Đo tỷ lệ cache hit của DAX | | | So Consumed với Provisioned | |

Và một lời khuyên: hãy đặt Auto Scaling cho cả chỉ mục phụ toàn cục chứ đừng chỉ đặt cho bảng chính. GSI có công suất riêng và throttle của nó ném ra đúng cùng một ngoại lệ — nên rất nhiều người tăng công suất bảng chính mãi mà vấn đề vẫn còn nguyên.

Câu 498 AWS Storage

A company has a requirement to store documents that will be accessed by a serverless application. The documents will be accessed frequently for the first 3 months, and rarely after that. The documents must be retained for 7 years.
What is the MOST cost-effective solution to meet these requirements?

  1. A

    Store the documents in an encrypted EBS volume and create a cron job to delete the documents after 7 years.

  2. B

    Store the documents in a secured Amazon S3 bucket with a lifecycle policy to move the documents that are older than 3 months to Amazon S3 Glacier, then expire the documents from Amazon S3 Glacier that are more than 7 years old.

  3. C

    Store the documents in a secured Amazon S3 bucket with a lifecycle policy to move the documents that are older than 3 months to Amazon S3 Glacier. Create an AWS Lambda function to delete the documents in S3 Glacier that are older than 7 years.

  4. D

    Store the documents in Amazon EFS. Create a cron job to move the documents that are older than 3 months to Amazon S3 Glacier. Create an AWS Lambda function to delete the documents in S3 Glacier that are older than 7 years.

Xem giải thích

Đáp án

**B — Lưu tài liệu trong một bucket S3 được bảo vệ, đặt luật vòng đời chuyển tài liệu cũ hơn 3 tháng sang S3 Glacier, rồi cho hết hạn những tài liệu ở Glacier quá 7 năm.

Vì sao đúng

Đề mô tả đúng một vòng đời dữ liệu điển hình, và luật vòng đời của S3 lo được toàn bộ: | Giai đoạn | Cơ chế | |---|---| | 3 tháng đầu, truy cập nhiều | S3 Standard | | Sau đó, hiếm truy cập | transition sang Glacier | | Sau 7 năm | expiration |

⚠ Điểm mấu chốt: luật vòng đời làm được CẢ transition lẫn expiration:

{"Rules": [{
  "ID": "vong-doi-tai-lieu",
  "Filter": {"Prefix": "tai-lieu/"},
  "Status": "Enabled",
  "Transitions": [
    {"Days": 90, "StorageClass": "GLACIER"}],
  "Expiration": {"Days": 2555},
  "AbortIncompleteMultipartUpload": {"DaysAfterInitiation": 7}}]}
aws s3api put-bucket-lifecycle-configuration \
  --bucket kho-tai-lieu \
  --lifecycle-configuration file://vong-doi.json

⚠ Và đó là lý do phương án C thừa:

C dùng vòng đời để chuyển sang Glacier
        ↓
    Rồi viết Lambda để xoá sau 7 năm
        ↓
    Nhưng `Expiration` trong chính luật
      đó làm được
        ↓
    → thêm một hàm phải viết, phải
      triển khai, phải giám sát
    → mà không được gì

⚠ Và Lambda tự viết còn kém tin cậy hơn:

Lambda chạy theo lịch
        ↓
    Phải liệt kê object, so ngày, xoá
        ↓
    Hàng triệu object → phân trang,
      timeout
        ↓
    Vòng đời của S3 chạy ở tầng dịch
      vụ
    → không tốn gì, không hỏng

⚠ Và vì sao phương án A sai:

A lưu trên EBS volume mã hoá
        ↓
    Ứng dụng là SERVERLESS
        ↓
    EBS gắn vào MỘT EC2 tại một thời
      điểm
        ↓
    Lambda không gắn EBS được
    → sai về mặt kiến trúc

⚠ Và EBS còn đắt hơn nhiều: | Kho | Giá xấp xỉ mỗi GB-tháng | |---|---| | EBS gp3 | 0,08 USD | | S3 Standard | 0,023 USD | | S3 Glacier Flexible | 0,0036 USD | | S3 Glacier Deep Archive | 0,00099 USD |

Giữ 7 năm trên EBS
        ↓
    Đắt hơn Glacier khoảng 22 lần
    → và không mở rộng được như S3

⚠ Và vì sao phương án D vòng vo:

D lưu trên EFS, cron chuyển sang
  Glacier, Lambda xoá
        ↓
    EFS đắt hơn S3 hơn 10 lần
        ↓
    Phải viết cron và Lambda
        ↓
    Và "cron" trên hạ tầng serverless
      cần một máy nào đó chạy
    → mâu thuẫn với chính đề bài

Ghi nhớ về chất lượng câu hỏi

⚠ Từ "Glacier" giờ mơ hồ — có BA lớp khác nhau: | Lớp | Truy cập | Giá xấp xỉ | |---|---|---| | Glacier Instant Retrieval | tức thì | 0,004 USD/GB | | Glacier Flexible Retrieval | phút tới giờ | 0,0036 USD/GB | | Glacier Deep Archive | 12-48 giờ | 0,00099 USD/GB |

Đề chỉ nói "S3 Glacier"
        ↓
    Viết trước khi có Instant Retrieval
      (2021)
        ↓
    Trong `StorageClass` của API,
      `GLACIER` = Flexible Retrieval
    → giá trị `GLACIER_IR` và
      `DEEP_ARCHIVE` là hai lớp còn lại

⚠ Và với tài liệu "hiếm truy cập" thì nên cân nhắc kỹ:

Hiếm nhưng CÓ truy cập
        ↓
    Glacier Flexible: phải khôi phục,
      chờ 3-5 giờ
        ↓
    Glacier Instant Retrieval: đọc ngay
        ↓
    Chỉ đắt hơn ~11%
    → thường là lựa chọn đúng hơn
{"Transitions": [
  {"Days": 90, "StorageClass": "GLACIER_IR"},
  {"Days": 730, "StorageClass": "DEEP_ARCHIVE"}]}

⚠ Và phí tối thiểu phải tính vào: | Lớp | Tối thiểu lưu | |---|---| | Standard-IA | 30 ngày | | Glacier IR, Flexible | 90 ngày | | Deep Archive | 180 ngày |

Giữ 7 năm
        ↓
    Vượt xa mọi mức tối thiểu
    → không phải lo khoản này

⚠ Và "bucket được bảo vệ" nên hiểu là nhiều lớp:

aws s3api put-public-access-block --bucket kho-tai-lieu \
  --public-access-block-configuration \
    BlockPublicAcls=true,IgnorePublicAcls=true,\
BlockPublicPolicy=true,RestrictPublicBuckets=true

aws s3api put-bucket-encryption --bucket kho-tai-lieu \
  --server-side-encryption-configuration '{
    "Rules": [{"ApplyServerSideEncryptionByDefault":
      {"SSEAlgorithm": "aws:kms",
       "KMSMasterKeyID": "<arn-cmk>"},
      "BucketKeyEnabled": true}]}'

aws s3api put-bucket-versioning --bucket kho-tai-lieu \
  --versioning-configuration Status=Enabled

⚠ Và giữ 7 năm thường là yêu cầu TUÂN THỦ — nên dùng Object Lock:

aws s3api put-object-lock-configuration \
  --bucket kho-tai-lieu \
  --object-lock-configuration '{
    "ObjectLockEnabled": "Enabled",
    "Rule": {"DefaultRetention": {
      "Mode": "COMPLIANCE", "Years": 7}}}'

⚠ Nhưng Object Lock XUNG ĐỘT với luật expiration:

Object Lock chế độ COMPLIANCE
        ↓
    Không ai xoá được, kể cả root
        ↓
    Luật vòng đời cũng không xoá được
        ↓
    → object hết hạn khoá rồi mới xoá
      được
    → đặt retention đúng 7 năm và
      expiration cũng 7 năm

⚠ Và Object Lock phải bật LÚC TẠO bucket:

aws s3api create-bucket --bucket kho-tai-lieu \
  --object-lock-enabled-for-bucket \
  --create-bucket-configuration \
    LocationConstraint=ap-southeast-1
Không bật lúc tạo
        ↓
    Phải mở ticket hỗ trợ để bật sau
    → hoặc tạo bucket mới và chuyển dữ
      liệu

⚠ Và versioning làm luật vòng đời phức tạp hơn:

{"Rules": [{
  "ID": "don-phien-ban-cu",
  "Filter": {},
  "Status": "Enabled",
  "NoncurrentVersionTransitions": [
    {"NoncurrentDays": 30, "StorageClass": "GLACIER_IR"}],
  "NoncurrentVersionExpiration": {"NoncurrentDays": 365},
  "Expiration": {"ExpiredObjectDeleteMarker": true}}]}
Versioning bật → xoá tạo delete
  marker
        ↓
    Phiên bản cũ vẫn tính tiền
        ↓
    Phải có luật riêng cho chúng
    → thiếu → dung lượng tăng mãi

⚠ Và ExpiredObjectDeleteMarker dọn delete marker mồ côi:

Mọi phiên bản đã bị xoá
        ↓
    Còn lại delete marker không trỏ
      vào gì
        ↓
    Nó không tốn tiền nhưng làm chậm
      `ListObjects`
    → nên dọn

⚠ Và ứng dụng serverless đọc tài liệu ở Glacier phải xử lý:

`GetObject` trên object Glacier
  Flexible
        ↓
    → lỗi `InvalidObjectState`
        ↓
    Phải gọi `RestoreObject` rồi chờ
    → thiết kế giao diện phải phản ánh
      điều này

Ba lợi ích của luật vòng đời: | Lợi ích | Chi tiết | |---|---| | Không viết mã nào | | | Chạy ở tầng dịch vụ, không hỏng | | | Vừa chuyển tầng vừa xoá | |

⚠ Và nên kiểm chứng bằng S3 Storage Lens:

aws s3control get-storage-lens-configuration \
  --account-id 111122223333 --config-id mac-dinh
Xem phân bố theo lớp lưu trữ
        ↓
    Sau 90 ngày phải thấy dữ liệu ở
      Glacier
    → nếu không, luật chưa áp đúng
      tiền tố

Vì sao các phương án khác sai

  • **C. Vòng đời chuyển sang Glacier, rồi Lambda xoá tài liệu quá 7 năm — đây là phương án gần nhất và kết quả cuối giống hệt, nhưng Expiration trong chính luật vòng đời làm được việc đó mà không cần viết, triển khai và giám sát thêm một hàm Lambda.
  • **D. Lưu trên EFS, cron chuyển sang Glacier, Lambda xoá — EFS đắt hơn S3 hơn 10 lần và phương án này cần một máy chạy cron, mâu thuẫn với kiến trúc serverless.
  • **A. Lưu trên EBS volume mã hoá + cron xoá — EBS gắn vào một EC2 tại một thời điểm, ứng dụng serverless không dùng được, và đắt hơn Glacier khoảng 22 lần.

Ghi nhớ

⚠ Bốn thành phần của luật vòng đời — bảng phải thuộc: | Thành phần | Việc | |---|---| | Transitions | chuyển sang lớp rẻ hơn | | Expiration | xoá object | | NoncurrentVersion* | xử lý phiên bản cũ | | AbortIncompleteMultipartUpload | dọn phần tải lên dở |

Từ khoá nhận diện:

"retain 7 years then delete" → Transition + Expiration trong một luật "Lambda to delete old objects" → thừa, dùng Expiration "rarely accessed but must be instant" → Glacier Instant Retrieval "compliance retention" → Object Lock

Ba lớp Glacier: | Lớp | Truy cập | |---|---| | Instant Retrieval | tức thì | | Flexible Retrieval | phút tới giờ | | Deep Archive | 12-48 giờ |

Ba lưu ý về Object Lock: | Lưu ý | Chi tiết | |---|---| | Phải bật lúc tạo bucket | | | COMPLIANCE không ai gỡ được | | | GOVERNANCE gỡ được với quyền đặc biệt | |

Ba lưu ý về versioning: | Lưu ý | Chi tiết | |---|---| | Phiên bản cũ vẫn tính tiền | | | Cần luật riêng cho NoncurrentVersion | | | Dọn delete marker mồ côi | |

Ba lưu ý về phí tối thiểu: | Lớp | Ngày | |---|---| | Standard-IA | 30 | | Glacier IR, Flexible | 90 | | Deep Archive | 180 |

Ba lưu ý về đọc dữ liệu lưu trữ: | Lưu ý | Chi tiết | |---|---| | Glacier Flexible cần RestoreObject | | | Instant Retrieval đọc thẳng được | | | Athena bỏ qua object chưa khôi phục âm thầm | |

Ba lưu ý về bảo vệ bucket: | Lưu ý | Chi tiết | |---|---| | Block Public Access ở cả hai cấp | | | Mã hoá mặc định + Bucket Key | | | Versioning chống xoá nhầm | |

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Storage Lens xem phân bố theo lớp | | | Kiểm luật có khớp đúng tiền tố không | | | Thử đọc một object đã vào Glacier | |

Và một lời khuyên: hãy cân nhắc Glacier Instant Retrieval thay vì Glacier Flexible cho tài liệu mà người dùng vẫn có thể cần mở ra. Chênh lệch giá chỉ khoảng 11%, nhưng khác biệt trải nghiệm là giữa "mở ngay" và "chờ ba tiếng" — và với tài liệu lưu trữ theo quy định, lần cần tới nó thường là lúc gấp nhất.

Câu 499 AWS Management & Governance

A company uses AWS Organizations. The company recently acquired a new business unit and invited the new unit’s existing account to the company’s organization. The organization uses a deny list SCP in the root of the organization and all accounts are members of a single OU named Production.

The administrators of the new business unit discovered that they are unable to access AWS Database Migration Service (DMS) to complete an in-progress migration.

Which option will temporarily allow administrators to access AWS DMS and complete the migration project?

  1. A

    Create a temporary OU named Staging for the new account. Apply an SCP to the Staging OU to allow AWS DMS actions. Move the new account to the Production OU when the migration project is complete.

  2. B

    Create a temporary OU named Staging for the new account. Apply an SCP to the Staging OU to allow AWS DMS actions. Move the organization's deny list SCP to the Production OU. Move the new account to the Production OU when adjustments to AWS DMS are complete.

  3. C

    Convert the organization's root SCPs from deny list SCPs to allow list SCPs to allow the required services only. Temporarily apply an SCP to the organization's root that allows AWS DMS actions for principals only in the new account.

  4. D

    Remove the organization's root SCPs that limit access to AWS DMS. Create an SCP that allows AWS DMS actions and apply the SCP to the Production OU.

Xem giải thích

Đáp án

B — Tạo OU tạm tên Staging cho tài khoản mới, gắn SCP cho phép hành động AWS DMS, đồng thời CHUYỂN deny list SCP của tổ chức từ root xuống OU Production. Khi xong việc thì chuyển tài khoản mới vào Production.

Vì sao đúng

Câu này kiểm tra một điều duy nhất: SCP gắn ở root áp xuống MỌI tài khoản trong tổ chức, không có ngoại lệ, và không có cách nào "cho phép lại" ở tầng dưới.

Yêu cầu của đề Cách đáp ứng
Tài khoản mới dùng được DMS gỡ deny list ra khỏi đường ảnh hưởng tới nó
Các tài khoản cũ vẫn bị deny list quản chuyển deny list xuống đúng OU chứa chúng (Production)
Chỉ tạm thời OU Staging bỏ đi sau khi migrate xong

⚠ Điểm mấu chốt: quyền hiệu dụng của một tài khoản là GIAO của mọi SCP trên đường từ root xuống nó:

Root (deny list SCP: Deny dms:*)
        ↓
    OU Production (SCP: Allow dms:*)
        ↓
    Tài khoản
        ↓
    → Deny ở root THẮNG — Allow ở dưới vô nghĩa

SCP không cấp quyền, nó chỉ đặt trần. Một Deny tường minh ở bất kỳ tầng nào là chốt chặn cuối cùng: không tầng nào bên dưới cởi được nó ra. Đây là khác biệt cốt lõi giữa SCP và IAM policy thường — trong IAM bạn có thể bù quyền bằng policy khác, còn với SCP thì đường đi từ root xuống là một chuỗi cổng nối tiếp, đóng một cổng là hết đường.

Vì thế cách duy nhất để tài khoản mới thoát khỏi Deny dms:* là làm cho nó không còn nằm dưới cái SCP đó nữa. Phương án B làm đúng hai việc cùng lúc:

  1. Chuyển deny list từ root xuống OU Production — các tài khoản cũ vẫn nằm trong Production nên trần của chúng không đổi một chút nào.
  2. Đặt tài khoản mới vào một OU khác (Staging) — nó không còn thừa hưởng deny list, và SCP Allow ở Staging mở đường cho DMS.

Kiểm tra trước khi chuyển — đừng làm mù:

# xem SCP nào đang gắn ở root
aws organizations list-policies-for-target \
  --target-id r-abc1 --filter SERVICE_CONTROL_POLICY

# chuyển deny list xuống OU Production
aws organizations attach-policy \
  --policy-id p-denylist01 --target-id ou-abc1-production
aws organizations detach-policy \
  --policy-id p-denylist01 --target-id r-abc1

Thứ tự attach trước, detach sau là cố ý. Làm ngược lại thì có một khoảng thời gian các tài khoản Production không bị deny list nào che — một cửa sổ không được phép tồn tại trong môi trường có kiểm soát tuân thủ.

Vì sao các phương án khác sai

  • A (tạo OU Staging + SCP Allow, nhưng giữ nguyên deny list ở root) — đây là phương án gần nhất và cấu trúc OU của nó hoàn toàn đúng: tách tài khoản mới ra một OU riêng chính là cách làm chuẩn. Nhưng nó bỏ sót đúng một bước quyết định — deny list vẫn nằm ở root, nên nó vẫn phủ xuống OU Staging. SCP Allow dms:* ở Staging không thắng nổi Deny ở root, và tài khoản mới vẫn không dùng được DMS. Đây là bẫy kinh điển: người học thấy "tạo OU riêng + allow" là đủ mà quên rằng root vẫn ở trên đầu.

  • C (đổi deny list thành allow list ở root) — đổi toàn bộ mô hình quản trị của tổ chức chỉ để chữa một việc tạm thời. Rủi ro cực lớn: allow list phải liệt kê đủ mọi dịch vụ mà mọi tài khoản đang dùng; thiếu một cái là cả tổ chức mất dịch vụ đó ngay lập tức. Ngoài ra SCP không lọc theo tài khoản — mệnh đề "chỉ cho principal trong tài khoản mới" không diễn đạt được bằng SCP theo cách đề mô tả.

  • D (gỡ hẳn SCP hạn chế DMS ở root, rồi Allow ở Production) — gỡ chốt bảo vệ khỏi toàn bộ tổ chức để phục vụ một tài khoản. Sau bước này mọi tài khoản đều dùng được DMS, kể cả những tài khoản chính sách không muốn cho. Chưa kể "Allow ở Production" cũng chẳng thêm quyền gì vì SCP không cấp quyền.

Ghi nhớ

⚠ Bốn quy tắc SCP — bảng phải thuộc: | Quy tắc | Hệ quả | |---|---| | SCP đặt trần, không cấp quyền | vẫn cần IAM policy thì principal mới làm được việc | | Quyền hiệu dụng = giao của mọi SCP từ root xuống | thêm một tầng chỉ có thể thu hẹp | | Deny tường minh không thể bị ghi đè ở tầng dưới | muốn thoát thì phải rời khỏi phạm vi | | SCP không áp cho management account | test SCP trong management account luôn "qua" — kết luận sai |

Từ khoá nhận diện:

"deny list SCP in the root" → mọi tài khoản đều dính, kể cả tài khoản mới mời vào "temporarily allow" → di chuyển phạm vi, không phải thêm Allow "apply an SCP to allow" ở tầng dưới root khi root đang Deny → LUÔN SAI "invited the existing account to the organization" → tài khoản vào là dính SCP ngay, đây thường là nguyên nhân sự cố

Kiểu SCP Cách hoạt động Rủi ro
Deny list mặc định cho hết, chặn cái liệt kê dễ sót dịch vụ mới ra mắt
Allow list mặc định chặn hết, cho cái liệt kê thiếu một mục là gãy dịch vụ đang chạy
Tầng chính sách Trả lời câu hỏi
SCP "Tổ chức có cho phép hành động này không?"
Permissions boundary "Trần của IAM entity này tới đâu?"
IAM policy "Principal này được làm gì?"
Resource policy "Tài nguyên này cho ai vào?"
Nơi gắn SCP Ảnh hưởng tới
Root mọi OU và mọi tài khoản thành viên
OU tài khoản trong OU đó và OU con
Tài khoản riêng tài khoản đó

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Xem SCP nào đang áp cho một tài khoản | aws organizations list-policies-for-target --target-id <account-id> | | Xem đường thừa kế đầy đủ | list-parents lặp lên tới root, gom SCP ở từng tầng | | Thử quyền thật | đăng nhập vào chính tài khoản thành viên đó chạy aws dms describe-endpoints |

Và một lời khuyên: hãy thử SCP trong một tài khoản thành viên, không bao giờ trong management account. SCP không áp cho management account — chạy thử ở đó thì lệnh nào cũng thành công, bạn kết luận "chính sách ổn rồi", còn thực tế mọi tài khoản khác đang bị chặn. Đây là lỗi im lặng đúng nghĩa: không có log, không có cảnh báo, chỉ có một kết luận sai được xác nhận bởi một phép thử sai chỗ.

Câu 500 AWS Analytics

A media company streams live events and records viewership metrics in real-time. The data is ingested through Amazon Kinesis Data Streams and then stored in Amazon S3. The company uses Amazon Athena to analyze viewership trends from the stored data. Initially, the Athena queries performed well, but as the data volume has grown over several months, query performance has degraded.

The solutions architect needs to optimize the query performance while keeping operational overhead low.

Which solution will effectively address the performance issue?

  1. A

    Configure the Kinesis Data Streams to categorize data into different S3 buckets based on the event type. Update the Athena queries to scan data from specific buckets based on the query requirements.

  2. B

    Create an Amazon Redshift cluster and use Redshift Spectrum to query the S3 data. Modify the Athena queries to run against the Redshift Spectrum layer for improved performance.

  3. C

    Configure the Kinesis Data Firehose delivery stream to partition the data in Amazon S3 by date and event type. Redefine the Athena table to include these partitions and modify the queries to specifically target relevant partitions.

  4. D

    Create an AWS Glue job to aggregate daily viewership data into summary tables and modify the Athena queries to use these summary tables.

Xem giải thích

Đáp án

C — Cấu hình Kinesis Data Firehose phân vùng dữ liệu trong S3 theo ngày và loại sự kiện, khai lại bảng Athena có các phân vùng đó, rồi sửa truy vấn để nhắm đúng phân vùng cần.

Vì sao đúng

Athena tính tiền và tính thời gian theo số byte quét được, không theo số dòng trả về. Truy vấn chậm dần theo tháng nghĩa là mỗi lần chạy nó đang quét cả kho — phân vùng là cách duy nhất khiến nó bỏ qua phần lớn dữ liệu ngay ở tầng liệt kê tệp.

Yêu cầu của đề Cách đáp ứng
Truy vấn nhanh trở lại partition pruning — không đọc tệp ngoài phân vùng
Chi phí vận hành thấp Firehose tự phân vùng, không phải dựng cụm gì
Không đổi công cụ đang dùng vẫn là Athena, chỉ khai lại bảng

⚠ Điểm mấu chốt: partition pruning xảy ra TRƯỚC khi đọc dữ liệu, không phải trong lúc lọc:

Truy vấn có WHERE ngay = '2026-09-01'
        ↓
    Athena đọc metadata phân vùng trong Glue Data Catalog
        ↓
    Loại ngay mọi thư mục S3 không khớp — không mở tệp nào trong đó
        ↓
    → chỉ quét đúng thư mục của ngày đó

Đây là chỗ nhiều người hiểu nhầm. WHERE ngay = '...' trên một cột dữ liệu thường buộc Athena đọc hết mọi tệp rồi mới lọc — chi phí không giảm chút nào. Cùng mệnh đề đó trên một cột phân vùng khiến Athena loại bỏ cả thư mục trước khi đọc byte nào. Cùng một câu SQL, chênh nhau vài trăm lần về lượng byte quét.

Firehose có sẵn hai cách phân vùng, và biết chọn cái nào là phần thực chất:

Cách Ra tiền tố kiểu Khi nào dùng
Phân vùng theo thời gian (mặc định) year=2026/month=09/day=01/ luôn có, không tốn thêm
Dynamic Partitioning event_type=play/year=2026/... khi cần phân vùng theo giá trị trong bản ghi như loại sự kiện

Đề đòi phân vùng theo cả ngày lẫn loại sự kiện, nên phải bật Dynamic Partitioning để lấy được event_type từ chính nội dung bản ghi.

Khai bảng cho đúng — dùng dạng Hive để Athena tự nhận phân vùng:

CREATE EXTERNAL TABLE luot_xem (
  user_id   string,
  duration  int,
  ts        timestamp
)
PARTITIONED BY (event_type string, year string, month string, day string)
STORED AS PARQUET
LOCATION 's3://cong-ty-metrics/luot-xem/';

-- nạp phân vùng mới (tiền tố dạng khoa=giatri thì dùng được lệnh này)
MSCK REPAIR TABLE luot_xem;
-- truy vấn nhắm đúng phân vùng
SELECT count(*) FROM luot_xem
WHERE event_type = 'play'
  AND year = '2026' AND month = '09' AND day = '01';

⚠ Cột phân vùng phải xuất hiện trong WHERE thì mới có tác dụng:

Bảng đã phân vùng, nhưng truy vấn không lọc theo cột phân vùng
        ↓
    Athena không loại được thư mục nào
        ↓
    → quét toàn bộ, chậm y như cũ, mà không báo lỗi gì

Vì sao các phương án khác sai

  • A (Kinesis Data Streams ghi vào các bucket S3 khác nhau theo loại sự kiện) — đây là phương án gần nhất và ý tưởng tách dữ liệu theo loại sự kiện là đúng hướng: nó thật sự giảm được lượng dữ liệu quét khi chỉ cần một loại. Nhưng nó sai ở ba điểm. Thứ nhất, Kinesis Data Streams không tự ghi ra S3 — Streams là bộ đệm, phải có Firehose hoặc ứng dụng tiêu thụ mới ghi được, nên bước này không tồn tại như mô tả. Thứ hai, tách theo bucket thay vì theo tiền tố phân vùng khiến mỗi loại sự kiện thành một bảng riêng — muốn truy vấn xuyên loại phải UNION thủ công. Thứ ba, nó không giải quyết chiều thời gian — trong một bucket, dữ liệu vẫn dồn lại theo tháng và vẫn phải quét hết.

  • B (dựng cụm Redshift, dùng Redshift Spectrum) — thêm hẳn một cụm phải vận hành, đi ngược yêu cầu "operational overhead thấp" nêu thẳng trong đề. Nặng hơn nữa, Redshift Spectrum quét S3 theo đúng cách Athena quét: dữ liệu không phân vùng thì Spectrum cũng quét toàn bộ. Đổi công cụ mà không đổi cách bố trí dữ liệu thì không giải quyết được nguyên nhân. Và câu "sửa truy vấn Athena chạy trên Redshift Spectrum" không có nghĩa — đó là hai công cụ khác nhau.

  • D (Glue job gộp dữ liệu hằng ngày thành bảng tổng hợp) — có ích, nhưng nó đổi luôn cái mà truy vấn trả lời được. Bảng tổng hợp chỉ trả lời câu hỏi đã được gộp trước; câu hỏi chi tiết ở mức bản ghi thì không còn dữ liệu. Đề nói "phân tích xu hướng" chứ không nói chỉ cần số liệu tổng hợp sẵn. Thêm nữa, nó thêm một Glue job phải lập lịch và giám sát, trong khi phân vùng thì Firehose làm miễn phí ngay lúc ghi.

Ghi nhớ

⚠ Bốn cách giảm byte quét trong Athena — bảng phải thuộc, theo thứ tự hiệu quả: | Cách | Mức giảm điển hình | Ghi chú | |---|---|---| | Phân vùng | vài chục đến vài trăm lần | mạnh nhất, phải khớp với cách truy vấn hay lọc | | Định dạng cột (Parquet/ORC) | 5–10 lần | chỉ đọc cột cần, lại nén tốt | | Nén (Snappy, GZIP) | 3–5 lần | Snappy tách khối được, GZIP thì không | | Gộp tệp nhỏ | tuỳ | nhiều tệp bé giết hiệu năng ở khâu liệt kê |

Từ khoá nhận diện:

"query performance degraded as data volume grew" → thiếu phân vùng "low operational overhead" + đang dùng Athena → giữ Athena, sửa cách bố trí dữ liệu "partition the data by date and ..." → gần như luôn là đáp án đúng của dạng câu này "create a Redshift cluster" khi đề đòi giảm vận hành → LUÔN SAI

Thành phần Vai trò thật
Kinesis Data Streams bộ đệm bản ghi, không tự ghi ra S3
Kinesis Data Firehose đường ống có quản lý, ghi ra S3 và phân vùng được
Athena máy truy vấn SQL trên S3, tính tiền theo byte quét
Glue Data Catalog nơi giữ định nghĩa bảng và danh sách phân vùng
Lệnh nạp phân vùng Dùng khi
MSCK REPAIR TABLE tiền tố theo dạng Hive khoa=giatri/
ALTER TABLE ... ADD PARTITION tiền tố không theo dạng Hive
Partition projection phân vùng nhiều tới mức nạp metadata cũng chậm

Ba việc kiểm chứng: | Việc | Cách | |---|---| | Xem truy vấn quét bao nhiêu byte | cột Data scanned trong lịch sử truy vấn Athena | | Xác nhận pruning có chạy | so byte quét khi có và không có mệnh đề lọc phân vùng | | Xem phân vùng đã nạp chưa | SHOW PARTITIONS ten_bang; |

Và một lời khuyên: hãy so con số "Data scanned" trước và sau khi phân vùng, đừng chỉ nhìn thời gian chạy. Thời gian chạy dao động theo tải chung của dịch vụ nên rất dễ đánh lừa; byte quét thì tất định. Quan trọng hơn: nếu bạn phân vùng xong mà quên đặt cột phân vùng vào WHERE, truy vấn vẫn chạy đúng và trả kết quả đúng — chỉ có điều nó quét toàn bộ như cũ. Không có lỗi, không có cảnh báo, hoá đơn không đổi, và bạn tin rằng mình đã tối ưu xong.