🍶

Dynamoについて学ぶ

2022/01/02に公開

はじめに

仕事でDynamoを使ったシステム設計を検討することになったが、RDBの経験しかないので戸惑うことが多かった。
その経験を生かしてDynamoについて基本から学習するための備忘録とした。

参考書籍

WEB+DB PRESS Vol.125の 特集3 速習DynamoDB AWSフルマネージドNoSQLの探求 の項目がまとまっていたので参考にした

https://www.amazon.co.jp/dp/B09JYT6M5M/

Dynamoの特長

  • 高いパフォーマンス(Amazonセール時に8929万回/秒を捌いた実績)
  • サーバー管理が不要 (サーバーレス)
  • トランザクションが使える(TransactWriteItems, TransactGetItems)
    • BatchGetItemやBatchWriteItemは処理が失敗しても後続処理は続けるのでACIDではないので注意
  • バックアップとリストアの仕組みあり
    • ポイントタイムリカバリ(PITR)により35日間内での時間指定でのリストアが可能
    • オンデマンドバックアップで既存のテーブルに影響なしにバックアップ取得できる
    • リストア時は別テーブルとして復旧される
  • データを暗号化して保存もできる

Dynamoが生まれた背景

Amazonの内部で利用していたDB。それまではRDBを使っていたが以下の点で使いづらかった。

  • クエリの大半が主キーによる参照でRDBでなくても良い
  • スケールアップするための運用負荷高い
  • ライセンス料の支払いこのコスパが悪い

これらが考慮されてNoSQL型のDBの検討がなされてDynamoが生まれた。
以下は一般的なRDBの特長としてメモ。

一般的なRDBの特長

表形式のデータを用いていて、関係モデルに基づいた構成を取っている。そのため、複雑な分析が得意。
強い一貫性を担保できるため、テーブル・カラムの追加変更でデータ設計への変更を吸収できることが多い。
一方で、スケールアウトの煩雑さが伴う。

データ設計の柔軟性

RDBは上述したようにデータ設計の変更に強い。一方で、NoSQLは大きなデータ設計変更には弱い。
その背景には、Dynamoのベストプラクティスにあるように 想定されるクエリがある程度固まってからテーブルの設計を行う という考え方の違いが大きい。
RDBはデータの関係性を考慮するが、Dynamoはデータを効率的に処理するためのモデリングを考慮するという点が異なる。
そのため、Dynamoで大きなデータ設計変更があった場合以下のような手順でテーブルを作り直すパターンがある。
具体的にはパーティションキーやソートキーに対して変更があった場合は以下のような手順を踏む。(Glueが便利)

OLAP処理への対応

RDBのような複数のテーブルを含んだ分析処理は弱い。
複雑なwhereや集計関数がないため、RDBと同じようなクエリを書くために、複数のScanや自前のアプリケーション側にロジックを書くことになり高コスト。
しかし、他のリソースと組み合わせることでRDBのようなクエリを組み立ててデータの参照ができる。

  • Amazon EMRでApache Hive起動する案
  • データをExportしてAmazon RedShift上で閲覧できるようにする案
  • データをS3にExportしてAthenaを利用する案

DynamoのTable構成

AWS Solutions Architect ブログ:参照の画像がわかりやすかったので抜粋。

Tableは複数のDBを持つ。このDB1つ1つがパーティションと呼ばれる。(1つのテーブルは1つ以上のパーティションから構成されている)

このパーティションの中には複数のItemが格納されている。
Itemが格納されるルールがある。
それはパーティションキーに指定した値をグループ化するというもの。

hogeId  -> Hash(hogeId)  -> 7B.... -> 1A 〜 9Zを格納するというルールのパーティションに追加
hoge2Id -> Hash(hoge2Id) -> C1.... -> A0 〜 D9を格納するというルールのパーティションに追加

パーティションの中に格納されるItemの構成は以下

  • Primary Keyはパーティションキーとソートキーの組み合わせで一意になるキーのこと
  • パーティションキーは上述したどのパーティションに書き込むが決まるキー
    • データ設計時にはパーティションキーに何を定義するかが非常に大事
      • カーディナリティが低くなると、特定のパーティションに対して負荷が集中しスロットリング発生するため
        • アクセスが集中するようなものをホットキーという
          • Dynamic Partitionが導入され一度スロットリングを検知すると、その後スロットリングが発生しないように、裏側で自動でパーティションが分割してくれる
  • ソートキーはパーティションキーが同じ場合、ユニークな値にするために使うキーという考え方で良い
  • Attributesにはその他の色々な値を詰め込める

Capacity Unitという考え方

  • 読み込み・書き込みどちらもCUを消費することで利用できる仕組み。このCUの消費量で課金される。
  • Scanを使うとRCUを大量消費するので必要かどうか確認しておく必要あり
    • Filterを使って絞り込んでいると思っても、その前にScanしてたら全件取得なのでRCU消費激しいことに注意
      • RCUの消費を抑えるのであれば、パーティションキーとソートキーで抽出するしかない
  • アクセスパターンが読めない新規サービスなどはオンデマンドモードでリリースするのが良い。
  • ある程度ワークロードが定まった段階でログを見つつプロビジョンモードに切り替えていく。
  • 今はAdaptive Capacityが導入されたのでキャパシティの希薄化に敏感になることもなくなった。
    • 1テーブル内のパーティション郡で1000WCU, 3000RCU, 10Gという制約があり、パーティション数に依存して平均されていた
      • 100パーティションあったら、1パーティションで10WCU, 30RCUしか使えなくなる(スロットリング発生しちゃう)

Discussion