中級読了 5 分

DynamoDB Auto Scaling (オートスケーリング) の設定方法

DynamoDB のオートスケーリングは、プロビジョンドテーブルの読み取りキャパシティと 書き込みキャパシティを、あなたが選んだターゲット使用率に近づくように調整します。 RCU/WCU を手で調整することも、最悪ケースの予約に 24 時間ずっと支払うこともなくなります。 本ガイドはキャパシティの話の実践編です。コンソールでの経路、CLI のコマンド、数値の実際の 選び方、そして鋭いスパイクをやはりスロットリングさせるタイミングの制約を扱います。 まだキャパシティモードを決めていないなら、 オンデマンド vs プロビジョンドから 始めてください — オートスケーリングはプロビジョンドにしか適用されません。

DynamoDB テーブルでオートスケーリングを有効にするには?

コンソールでは、テーブルを開いて Additional settingsRead/write capacityEdit と進み、Provisioned を選び、読み取りキャパシティ、書き込みキャパシティ、 またはその両方について Auto scalingOn にします。それぞれに最小値、最大値、 そしてターゲット使用率 (20~90 パーセントの範囲で設定可能) を与えます。CLI からは、 aws application-autoscaling でスケーラブルターゲットを登録し、ターゲット追跡 スケーリングポリシーをアタッチします。コンソールで作成したテーブルは、デフォルトで オートスケーリングが有効になります。

オートスケーリングが実際にすること

スケーリングポリシーは Application Auto Scaling に対して、テーブルの「消費キャパシティ対プロビジョンドキャパシティ」の比率を、設定した 最小キャパシティと最大キャパシティの範囲内でターゲット使用率の近くに保つよう 指示します。内部では、上側と下側の境界に対して CloudWatch アラームのペアが作成されます。 消費がどちらかを越えると、Application Auto Scaling が UpdateTable 呼び出しを発行して プロビジョンドキャパシティを動かします。

セットアップの前に、構造上の事実が2つ効いてきます。

  • ポリシーはテーブルごと、かつ GSI ごと。 すべてのグローバルセカンダリインデックスは 自身のプロビジョンドスループットを持つので、それぞれに独自のポリシーが必要です (あるいはコンソールの「same settings for all GSIs」チェックボックス)。スケールの足りない GSI はベーステーブルの書き込みをスロットリングし得ます — GSI がベーステーブルをスロットリングする理由 を参照。
  • コンソールで作成したテーブルはデフォルトで有効、あとから追加した GSI は構築中は スケールしない。 既存テーブルに追加した新しい GSI は、バックフィルの間は手動キャパシティ で始まります — ポリシーがアタッチされるまで見張っておきましょう。

引き受けることになるタイミング

オートスケーリングは事後反応型で、その反応時間は固定です — AWS はアラームのデータポイント数 が調整できないことを文書化しています:

  • スケールアップは、消費キャパシティが連続2分間ターゲットを超えたあとに発動します (加えて CloudWatch のアラーム遅延が数分まで乗ります)。
  • スケールダウンは、ターゲットを下回る連続15個の1分間データポイントを待ちます。
  • どちらが発動しても、UpdateTable の呼び出しは適用までに数分かかり、その間、古い 上限を超えるリクエストはスロットリングされます
DynamoDBApplication AutoScalingCloudWatchTrafficDynamoDBApplication AutoScalingCloudWatchTrafficrequests above the old ceiling throttle until the update landsconsumed > target, minute 1consumed > target, minute 2alarm firesUpdateTable (several minutes)

超過から新しいキャパシティまでの、この約5分という下限がこの機能の正直な限界です。 オートスケーリングが吸収できるのは_伸びていく_トラフィックであって、段差になる トラフィックではありません。1分で負荷が3倍になるフラッシュセールは、どんなポリシーを 組んでもプロビジョンドキャパシティではスロットリングします。その形のトラフィックが 求めるのはオンデマンドで、直前のピークの 2倍までを即座に受け止めます (そして 30 分以内にその2倍を超えるとスロットリングします — 同じ物理法則の、オンデマンド版です)。

コンソールでの設定

既存のテーブルの場合 (AWS の手順):

  1. DynamoDB コンソール → Tables → 対象のテーブルを選びます。
  2. Additional settings タブ → Read/write capacityEdit
  3. Capacity mode: Provisioned
  4. Table capacity の下で、読み取り、書き込み、またはその両方について Auto scalingOn に切り替え、それぞれに Minimum capacity unitsMaximum capacity unitsTarget utilization を設定します。
  5. 必要なら同じ設定をすべての GSI に適用し、Save します。

知っておく価値のあるコンソールの制限が1つあります。クールダウンはそこには公開されていません。 AWS 自身のドキュメントは「スケールインとスケールアウトのクールダウン時間の設定など、より 高度な機能」については CLI を使うよう案内しています。

CLI での設定

ディメンションごとに2つの呼び出しです。スケーラブルターゲット (最小/最大の範囲) を登録し、 次にターゲット追跡ポリシーをアタッチします。 AWS の CLI ウォークスルー から、テーブルの書き込みキャパシティについてそのまま引用します:

aws application-autoscaling register-scalable-target \
    --service-namespace dynamodb \
    --resource-id "table/TestTable" \
    --scalable-dimension "dynamodb:table:WriteCapacityUnits" \
    --min-capacity 5 \
    --max-capacity 10

ポリシーの設定は JSON ファイルに置きます:

{
  "PredefinedMetricSpecification": {
    "PredefinedMetricType": "DynamoDBWriteCapacityUtilization"
  },
  "ScaleOutCooldown": 60,
  "ScaleInCooldown": 60,
  "TargetValue": 50.0
}
aws application-autoscaling put-scaling-policy \
    --service-namespace dynamodb \
    --resource-id "table/TestTable" \
    --scalable-dimension "dynamodb:table:WriteCapacityUnits" \
    --policy-name "MyScalingPolicy" \
    --policy-type "TargetTrackingScaling" \
    --target-tracking-scaling-policy-configuration file://scaling-policy.json

読み取りの場合は、ディメンションを dynamodb:table:ReadCapacityUnits に、メトリクスを DynamoDBReadCapacityUtilization に差し替えます。GSI の場合は、リソース ID が table/TestTable/index/test-index になり、dynamodb:index:* のディメンションを使います。 したがって GSI を3つ持つテーブルで両方のディメンションをスケールさせるには、 ターゲット/ポリシーのペアが8組必要です — スクリプト化しましょう。

2つのクールダウンは DynamoDB ではデフォルトが 0 で、CLI からしか触れないつまみです。 ScaleOutCooldown はキャパシティ増加の間隔の最小秒数 (より大きなスケールアウトは、それでも 即座に通ります)、ScaleInCooldown は次の引き下げをブロックします — ただしスケールアウトは、 スケールインのクールダウンを待つのではなく中断させます。

数値の選び方

ターゲット使用率は、余裕とコストのダイヤルです。ターゲットが T パーセントなら、 消費キャパシティのおよそ 100/T 倍を支払うことになります。70% のターゲットは定常 トラフィックの上に約1.4倍の余裕を、50% のターゲットは2倍を買います。ターゲットが低いほど 急な伸びをスロットリングなしで乗り切れ、高いほど予約の無駄が減ります。設定できる範囲は 20~90% です。

このダイヤルはそのまま請求につながります。現在の us-east-1 の料率から (導出は DynamoDB はオートスケールできますか?と同じ)、 プロビジョンドキャパシティは使用率 100% ならリクエストあたりオンデマンドより約3.46倍 安く、損益分岐点は使用率約29% にあります。オートスケーリングの仕事は実際の 使用率をターゲットの近くに保つことなので、ターゲットは実質的に割引率の選択になります。 70% を保てばプロビジョンドはオンデマンドより約2.4倍安く、50% なら約1.7倍、約29% を 下回るなら、代わりにオンデマンドにすべきです。自分のワークロードの数値は 料金計算ツールで確認してください。

最小キャパシティはスパイクに対する床です。オートスケーリングが反応するのに必要な 約5分の間、_すでにそこにある_キャパシティがこれです。平均トラフィックからではなく、 スロットリングせずに吸収しなければならない最も鋭いバーストから決めましょう。

最大キャパシティは暴走に対する保護です — バグ、暴走した Lambda のループ、負荷テストが 請求し得る額の上限になります。現実的なピークより上に設定し、そこに到達することは通常の 運用ではなくアラートとして扱いましょう。

スケールダウンにはクォータがあります。 プロビジョンドの引き下げはトークンバケットから 出てきます。UTC の各日は使える4回から始まり、1時間ごとに1回ずつ (保持は最大4回まで) 貯まって、1テーブルあたり1日最大27回の引き下げになります — GSI の上限は別枠ですが、 テーブルとインデックスの両方を引き下げる1つのリクエストは、どちらか一方でもクォータが 足りなければ丸ごと拒否されます。オートスケーリングの保守的な15分のスケールダウンは、実際 にはすでにこれを尊重していますが、スパイクのあとキャパシティがゆっくりとしか下がらないのは このためであり、振動するトラフィックが平均より高い位置に張り付いたまま1日を終えるのも このためです。

DynoTable でやってみる

最小値のサイジングも、ターゲットの検証も、推測ではなく実際の数値から始まります。アイテムが どれくらい大きいか、いくつあるか、代表的な読み取りや書き込みが実際にどれだけ消費するか。 DynoTable のテーブルビューはライブのアイテム数とテーブルサイズを表示し、 クエリのコストプレビューは実行前にステートメントの RCU 見積もりを 示します — キャパシティ計画がそれで作られているのと同じ数値です。1つのアイテムを サイジングするには、無料のアイテムサイズ計算ツール がその RCU/WCU のフットプリントを計算します。

落とし穴と次のステップ

  • オートスケーリングはパーティションごとの物理法則には勝てません。 ホットキーは、 キャパシティに余裕があってもスロットリングします — ホットパーティションアダプティブキャパシティを参照。
  • GSI を忘れずに。 各インデックスはそれ自身でスケールし (あるいはスロットリングし) ます。
  • リザーブドキャパシティはプロビジョンドの上にしか積み上がりません。 オートスケーリング がほとんど動かないほどワークロードが安定しているなら、次の割引はリザーブドキャパシティ (Standard テーブルクラス、プロビジョンドモード限定) です — オンデマンドのテーブルでは 使えません。
  • 最初の1日は見張る。 CloudWatch でプロビジョンドの線に対して ConsumedReadCapacityUnits / ConsumedWriteCapacityUnits を見れば、ターゲットが 保たれているのか振動しているのかがすぐ分かります。

キャパシティはコストモデルの1つの軸で、もう1つはクエリが何を_消費する_かです — Query と ScanSQL スキャンのコストモデルがその半分を扱います。

DynoTable をダウンロードして、テーブルにキャパシティの数値をコミットする前に、 実際のサイズ、アイテム数、クエリごとのコストを読み取りましょう。

更新日