AWS / SAP-C02

SAP-C02-093 · セクション 10 / タスク 2.5

Performance要件からPurpose-built Architectureを選択する

コンピューティング / ストレージ / データベース / キャッシュ / バッファ / レプリカ / 分析基盤 / アーキテクチャ選択

パフォーマンス目標を満たせないとき、最初に「EC2を大きくする」「データベースを大きくする」と決めてはいけません。

アプリケーション全体の性能は、コンピューティング、ストレージ、データベース、キャッシュ、バッファ、レプリカ、分析基盤など、複数の層の組み合わせで決まります。

重要なのは、

遅い
↓
何かを大きくする

ではなく、

パフォーマンス目標
↓
実測値
↓
アクセスパターン
↓
ボトルネック / 制約
↓
問題を解くべき層
↓
適切な構成要素
↓
組み合わせ
↓
再測定

と判断することです。

ゴール

性能問題を見たときに、

コンピューティング
ストレージ
データベース
キャッシュ
バッファ
レプリカ
分析基盤

のどこで解くべきかを切り分け、必要なら複数の構成要素を組み合わせてアーキテクチャを選択できることがゴールです。

1. 最初に「対策」ではなく「制約」を特定する

例えば、APIのレイテンシーが悪化しているとします。

この情報だけでは、対策は決まりません。

同じ「APIが遅い」でも原因は異なります。

実測された状態主に確認する層
CPUが飽和しているコンピューティング
ストレージI/O待ちが支配的ストレージ
特定キーへの書き込み集中データベース
同じデータを何度も読み取るキャッシュ
多数の異なる読み取りがDBへ集中レプリカ
短時間だけ到着量が処理量を超えるバッファ
分析処理がトランザクション処理と競合分析基盤

つまり、

症状
≠
ボトルネック

です。

「レスポンスが遅い」は症状です。

実際に性能を制限している場所を測定し、その場所へ対策を当てます。

2. 問題のある層と対策する層を合わせる

基本原則は、

コンピューティングの処理能力不足
→ コンピューティング層

ストレージI/Oの制約
→ ストレージ層

書き込みやデータアクセスの偏り
→ データベース層

同じ読み取りの反復
→ キャッシュ層

大量の読み取り
→ レプリカ

一時的な流入超過
→ バッファ

分析処理との資源競合
→ 分析基盤の分離

です。

例えば、

DB CPU
→ 100%

アプリケーションCPU
→ 25%

なのに、アプリケーションサーバーだけ増やしても、ボトルネックを直接解消できません。

逆に、

アプリケーションCPU
→ 95%

DB
→ 余裕あり

ストレージ
→ 余裕あり

なら、データベースを変更しても主原因は残ります。

重要なのは、

性能問題が存在する層
=
最初に対策を検討する層

という対応関係です。

3. 個別技術ではなく「どの層を変えるか」を決める

ここでは各サービスの機能を覚え直すのではなく、実測結果から変更対象を選びます。

状況優先して検討する変更
CPUが継続的に飽和し、水平分散可能コンピューティング能力
I/O待ちが処理時間を支配ストレージ構成
書き込み集中やアクセス偏りデータベース設計
同じ結果を何度も取得キャッシュ
多数の読み取りを別経路へ分散可能レプリカ
短時間だけ処理要求が急増し、非同期化可能バッファ
分析処理が本番トランザクションと競合分析基盤の分離

ここで見るのは、

どの技術が優れているか

ではなく、

どの層が現在の制約を持っているか

です。

4. 1つの要件だけで決めない

実際の設計では、複数の条件を同時に満たす必要があります。

例えば、

短時間に大量流入
+
処理は非同期可能
+
15分以内に完了
+
常時最大能力は不要

なら、単に処理能力を増やすだけではなく、

一時的な流入を吸収する仕組み
+
必要時に処理能力を増やす仕組み

を組み合わせる方が要件に合います。

また、

同じデータの反復読み取り
+
その他の読み取りも大量

なら、

キャッシュだけ

または、

レプリカだけ

ではなく、両方を異なる読み取りパターンへ割り当てる場合があります。

5. 同じ「読み取り負荷」でも解決位置は異なる

読み取り負荷が高いというだけでは、対策は決まりません。

見るべきなのは、

同じ結果を繰り返しているか

それとも、

多数の異なるデータを読んでいるか

です。

反復される読み取り
→ キャッシュで要求自体を減らす

多数の異なる読み取り
→ レプリカで読み取り先を分散する

と考えます。

両方が存在する場合は、

キャッシュ
+
レプリカ

を組み合わせます。

ここで重要なのは個別サービスの機能ではなく、

同じ読み取り負荷でも
原因によって解決する層が異なる

ことです。

6. 一時的な流入超過と処理能力不足を分ける

次の2つは似ていますが、同じではありません。

一時的に
到着量 > 処理量

と、

長時間にわたり
到着量 > 最大処理量

です。

前者では、非同期化できるなら一時的な差をバッファで吸収できます。

しかし後者では、バッファを追加しただけでは未処理件数が増え続けます。

したがって、

短時間の急増
→ バッファを評価

継続的な処理能力不足
→ 処理能力の増加も必要

と判断します。

必要であれば、

バッファ
+
処理側の伸縮

を組み合わせます。

7. 同期性は構成選択を制約する

非同期化できるかどうかは重要な制約です。

例えば、

画像変換
メール送信
集計処理

のように後から処理してよいものは、バッファを利用できる場合があります。

一方、

在庫を確保できたか
決済に成功したか

をその場で返す必要がある処理では、処理そのものを後回しにできません。

この場合は、

同期経路上にある
実際のボトルネック

を解決します。

つまり、

非同期化できる

こと自体が、アーキテクチャ選択の決定条件になります。

8. 分析処理を同じ性能境界に置く必要があるか

トランザクション処理と分析処理では、アクセスパターンが大きく異なる場合があります。

例えば、

注文処理
+
数年分の大規模集計

を同じデータベースで実行すると、分析処理が本番処理の性能へ影響することがあります。

分析結果に一定の遅延を許容できるなら、

トランザクション処理
        │
        └── データ連携
                ↓
             分析基盤

のように分離できます。

判断するのは、

分析処理を
本番トランザクションと
同じ性能境界に置く必要があるか

です。

9. Purpose-built Architectureはサービス数を増やすことではない

目的特化型アーキテクチャは、

AWSサービスをたくさん使う

ことではありません。

同じアプリケーションでも、

大きなオブジェクト
IDによる低レイテンシー参照
大量履歴データへの分析

のようにアクセス方法が異なる場合があります。

その場合、

アクセスパターンA
→ 構成要素A

アクセスパターンB
→ 構成要素B

アクセスパターンC
→ 構成要素C

と分離します。

必要な役割が1つで済むなら、無理に複数サービスへ分ける必要もありません。

重要なのは、

アクセスパターンごとに
適切な責任を割り当てる

ことです。

10. 複数の性能問題は複数の層で解く

実際のシステムでは、ボトルネックが1つとは限りません。

例えばECサイトで、

商品情報
→ 同じデータを大量に読み取る

購入履歴
→ 多数の異なるデータを読み取る

画像変換
→ 短時間だけ要求が急増し、非同期可能

注文DB
→ 分析処理と競合

しているとします。

この場合、

商品情報
→ キャッシュ

購入履歴
→ レプリカ

画像変換
→ バッファ + 処理側の伸縮

分析
→ 分析基盤へ分離

のように、それぞれの問題へ別の構成要素を割り当てます。

                    ┌──── キャッシュ
                    │
利用者 → コンピューティング ─┼──── データベース
                    │              │
                    │              └──── レプリカ
                    │
                    └──── バッファ ───→ ワーカー

トランザクションデータ
        │
        └────────────→ 分析基盤

重要なのは、

どのAWSサービスが高性能か

ではなく、

どの性能問題を
どの構成要素に担当させるか

です。

11. 1つの改善でボトルネックが移動する

性能改善では、

現在のボトルネックを解消

すると、

別の層

が次のボトルネックになることがあります。

例えば、

DB読み取り負荷
↓
キャッシュ導入
↓
DB負荷低下
↓
アプリケーションCPUが次の制約

となることがあります。

また、

ワーカーを大量に増加
↓
DB書き込み増加
↓
DBが次の制約

となることもあります。

したがって、

変更
↓
再測定
↓
性能目標を確認
↓
次のボトルネックを確認

を繰り返します。

12. 代表的なアンチパターン

状況誤った方向見直す方向
DBがボトルネックEC2だけ巨大化DBへの要求原因を確認
同じ読み取りを反復レプリカだけ追加キャッシュで要求自体を減らせるか確認
多数の異なる読み取りキャッシュだけ追加レプリカによる分散を評価
短時間の非同期バースト常時最大能力バッファ + 処理側の伸縮を評価
長期的な処理能力不足バッファだけ追加処理能力も増やす
書き込みホットスポットリードレプリカ追加書き込み分散・DB設計を確認
ストレージI/O飽和コンピューティングだけ増加ストレージ性能を確認
OLTPと大規模分析が競合同じDBを巨大化分析基盤への分離を評価

13. SAP-C02での判断フロー

問題文を読んだら、次の順序で考えます。

1. 性能目標は何か
   ↓
レイテンシー?
スループット?
リクエストレート?
IOPS?

2. どこが性能目標を妨げているか
   ↓
コンピューティング?
ストレージ?
データベース?
読み取り?
書き込み?
分析?

3. アクセスパターンは何か
   ↓
反復読み取り?
多数の異なる読み取り?
書き込み集中?
一時的な急増?
継続負荷?

4. 制約は何か
   ↓
同期必須?
非同期可能?
古い読み取りを許容?
整合性要件?
互換性要件?

5. 解くべき層を決める
   ↓
コンピューティング
ストレージ
データベース
キャッシュ
バッファ
レプリカ
分析基盤

6. 独立した問題が複数あるなら
   構成要素を組み合わせる

7. 変更後に再測定する

この順序で、

サービス名から正解を探す

のではなく、

要件
↓
制約
↓
ボトルネック
↓
アーキテクチャ

で判断します。

まとめ

パフォーマンス設計では、

大きいインスタンス
高いスペック
多くのサービス

を選ぶこと自体が目的ではありません。

重要なのは、

どこが性能を制限しているか

を見つけ、

その問題を解ける層

へ対策を配置することです。

基本判断は、

コンピューティング能力不足
→ コンピューティング

ストレージI/O制約
→ ストレージ

書き込み / アクセス偏り
→ データベース

反復読み取り
→ キャッシュ

大量読み取り
→ レプリカ

一時的な非同期バースト
→ バッファ

分析との資源競合
→ 分析基盤へ分離

です。

複数の独立した問題があるなら、それぞれへ異なる構成要素を割り当てます。

最後は必ず、

変更
↓
再測定
↓
性能目標を確認

まで行います。

主要AWS公式資料

  • AWS Certified Solutions Architect - Professional SAP-C02 試験ガイド — Domain 2 / Task 2.5
  • AWS Well-Architected Framework — Performance Efficiency Pillar
  • Amazon EC2 Auto Scaling User Guide
  • Amazon RDS User Guide — Read Replicas
  • Amazon ElastiCache User Guide
  • Amazon SQS Developer Guide
  • Amazon Athena User Guide

理解確認

このページの内容を4問で確認します。

理解確認4問へ →