内容
DynamoDBでちょっとした社内システムを作ったところ、容量の設定が適当すぎてユーザ影響がでていたので、対処を行いました。
備忘録兼、こんなかんじになるよ~という記事になります。知らない方向け。
はじめに
DynamoDBの課金について
・RDSと違いプロビジョニング自体にはお金が掛からないが、読み書きの動作に対して課金される
・課金モードは、オンデマンド(従量課金)とプロビジョンド(定額課金)を選べる。
・プロビジョンドで事前に設定したスループットを超えると、読み書きできない、が発生する
普段RDBMSしか使ってなかったりすると知らなかったりすると思います。僕は知りませんでした。 びっくりするから先に言ってくれ。
どうすればいい?
調べた感じ、下記のような感じでよいようです。
・とりあえず難しく考えずにプロビジョンドにAutoScalingを設定する
(AutoScalingの設定自体には課金が発生せず正直これといったデメリットがない)
・それでも強烈なスパイクでスロットルが発生しそれが許されない場合だけオンデマンドにする。
具体的な料金比較やキャパシティの計算については、古いですがこちらの記事が参考になります。
オンデマンドは基本高いみたいです。経理に怒られそう。
実際にやってみた
今回元々低いキャパシティを雑に設定していて、ユーザー数が増えた時に読み込みスロットリングが発生してしまいました。
ここにAutoScalingを設定したところの実際の挙動を貼っていきたいと思います。
設定はこんな感じ
DynamoDBから編集したいテーブルを選択し、「追加の設定」タブから、読み込み/書き込みキャパシティの編集セクションについて、右上の編集をクリック、設定を変更していきます。
今回読み込みのスロットリングが発生したことから、テーブルのキャパシティ→読み込みキャパシティで、
・AutoScalingをオン
・最小キャパシティユニット、最大キャパシティユニット、ターゲット使用率を入力
・「すべてのグローバルセカンダリインデックスに同じ読み込みキャパシティー設定を使用」にチェック
で、変更を保存。(今回すべてのGSIに設定しましたが、GSI毎での設定もできるみたいです)
最大最小の値は、モニタリングタブで、テーブルやインデックスの「読み取り使用量(平均単位/秒)」のグラフを確認しました。
今回該当するインデックスの実際の読み取り使用量が120程度だったので、ざっくり30~300と設定。
ターゲット使用率は少しわかりにくい項目ですが、実際の容量が設定値のXX%になるように設定されます、ということのようです。
例えば70%で設定すれば、今回は120が70%になるので、120/0.7=170くらいに設定値が動く予想。
結果
結果はこのようになりました。
・モニタリングタブ→該当のGSIのグラフ
左側のグラフで、07:20より前ではGSIの読み取り使用量(青の線)が既存設定の容量(赤の線)を大きく超えていたため、右側のグラフで「読み取り調整されたイベント」が発生していました。この「読み取り調整されたイベント」がスロットリングのことです。
設定を変更した07:20以降は読み取り容量が181に自動で変更され、「読み取り調整されたイベント」がゼロになっています。
・インデックスタブ→読み込みキャパシティー
AutoScalingが適用され、「現在プロビジョニングされているユニット」の値が181になりました。
・その後
ユーザー数の上下動に対して、AutoScalingが容量を都度変更してくれていることがわかります。
スロットリングは設定以降発生しませんでした。めでたしめでたし。
補足
今回テーブルだけじゃなくGSIに対しても一括でAutoScalingを適用しました。
そもそもインデックスに容量を設定するって意味わからなくないですか?僕は分かりません。
GSIというのは、NoSQLで「このキーで検索したい」というときに設定するものですが…
調べたところ、このGSI、内部的には一個設定するごとに一個の「射影テーブル」が作成され、別のパーティショニングが行われた新しいテーブルが作成されているそうです。
つまり、GSIごとに別個のテーブルになっているため、元のテーブルに対してスロットリングが発生しているのか、GSIでできた射影テーブルに対してスロットリングが発生しているのか、というのも別 ということらしいです。テーブルが増えているから、RCU/WCUも別なんですね。
今回のケースではGSIのテーブルにだけスロットリングが発生していたので、実は該当GSIのキャパシティだけを設定すれば十分だったようです。確認したところ、確かにGSIのRCUは変動しましたが、テーブル自体のRCUは30のまま変わりませんでした。まぁ、難しいことを考えずに全部AutoScalingにしておけばいいんじゃないかなと思うんですが、どうなんでしょうか。
このへんの仕組み含め、DynamoDBの中身についての解説はこちらの方の記事が詳しかったです。ぜひ参考にしてみてください。
おわりに
実際のDBの状況によって適切な設定が変ってくるものなので、判断が難しい場合はサポートケースをオープンして聞いてみるのも良いかもしれません。餅は餅屋ということです。良いDynamoDBライフをお過ごしください。