Shohhei1126's Blog

Amazon DynamoDBをざっとさらってみる

暇なのでAmazon DynamoDBをさらってみます。

参考: Core Components of Amazon DynamoDB

特徴

フルマネージドのNoSQLデータベースで簡単にセットアップできてレプリケーションやスケールアップもダウンタイムなしでできるようです。

保存されたデータはすべて暗号化されますが実装上特に意識する必要はないです。デフォルトの暗号化キーもありますがAWS KMSを使って任意のキーを使うこともできるようです。

またTTLを設定することで自動でデータを消すことができるのでキャッシュ的な使い方や不要な古いデータを消すことでインフラコストを削減することもできます。

もちろんバックアップもあります。

コアコンポーネント

テーブル, アイテム, アトリビュートがコアコンポーネントになります。

テーブルは他のDBと同様UsersとかPostsとかエンティティ単位で作るものです。アイテムはRDBで言うところのレコード、アトリビュートはカラムにあたります。

ただしアトリビュートはネストできる点が異なります。一応32階層まで深くできるようですが訳が分からなくなりそうなのでせいぜい1,2階層くらいにしておくのがよさそうです。

Users // テーブル
[
  { // アイテム
    "UserID": 1,
    "Name": "smith", // アトリビュート
    "Address": { // ネストされたアトリビュート
      "ZipCode": "1234",
      "City": "Fukuoka",
    }
  },
]

プライマリーキー

プライマリーキーはパーティションキー単体のものとそれにソートキーを組み合わせたものの二種類があります。

前述のUsersテーブルはUserIDが、以下のPostsテーブルはUserIDPostIDが主キーになります。

Posts
[
  {
    "UserID": 1, // パーティションキー
    "PostID": 1, // ソートキー
    "Content": "What's up?",
    "Category": "Sports",
  }
]

パーティションキーはハッシュアトリビュートとも言われるようで、これをDynamoDBのハッシュ関数に入れてその結果を元にどのパーティションに保存するかを決めるところに由来しているようです。この分散の仕組みはGCPのCloud Spannerに似ていますね。

ソートキーもレンジアトリビュートという言われるようで、同じパーティションキーのアイテムをソート済みで物理的に近くに保存するところに由来しています。

セカンダリーインデックス

セカンダリーインデックスを追加することでキー以外でクエリを発行することができます。

グローバルとローカルの二種類あって前者がパーティションキー、ソートキーとも異なるもので、後者が同じパーティションキーでソートキーが異なるものです。グローバルインデックスは20個、ローカルインデックスは5個と上限があります。

前述のPostsテーブルにCategoryContentというインデックスを追加しました。

CategoryContent
[
  {
    "Category": "Sports", // セカンダリインデックスのパーティションキー
    "Content": "What's up?", // セカンダリインデックスのソートキー
    "UserID": 1,
    "PostID": 1,
  }
]

インデックスを追加した元のテーブルをベーステーブルと呼びます。インデックス"CategoryContent"のベーステーブルはPostsになります。ベーステーブルへの追加、更新、削除は自動的にインデックスにも反映されます。

またインデックスに属性を追加することもできるのでクエリによってはベーステーブルを読まずに実行できるのでパフォーマンスも良くなりそうです。ベーステーブルのキー属性(ここではUserIDとPostID)は自動でインデックスに追加されます。

DynamoDBストリーム

DynamoDB Streamsによりデータの追加、更新、削除のイベントを順序保証された状態でほぼリアルタイムで受け取ることができるようです。

追加時はすべての属性を含んだアイテム全体が、更新時は更新された属性のbeforeとafterが、削除時はそのアイテム全体がキャプチャーされます。ストリームレコードにはその他テーブル名やイベントのタイムスタンプなどのメタデータも含まれるようです。

ストリームレコードは24時間経つと自動で削除されます。

DynamoDB API

参考: DynamoDB API

APIはコントロールプレーン(RDBでいうことろのDDL)、データプレーン(RDBでいうところのDML)、ストリーム、トランザクションの4つに別れています。

Read, Writeともトランザクションに対応してますね。

命名規則

参考: Naming Rules

名前はすべてUTF8でエンコードする必要があり大文字と小文字が区別されます。

テーブル名とインデックス名は3から255文字の間にする必要があり、英数字とアンダースコア、ハイフン、ドットのみ使用可能。アトリビュートは1から255文字まで。

予約語やスペシャルキャラクターもありますが後ほど。

データタイプ

参考: Data Types

データタイプはスカラータイプ、ドキュメントタイプ、セットタイプの3つに分けられます。スカラータイプは言わずもがな、ドキュメントタイプはJSONのようなネストした属性でMapやListのようなもの、セットタイプはスカラータイプのセットを保持します。

主キーだけはスキーマ定義する必要がありstring、number、binaryのいずれかで定義しなければなりません。逆に言えば主キー以外はスキーマを定義する必要はありません。

スカラータイプはnumber, string, binary, Boolean, nullの5種類のみで各言語ライブラリの実装でDate, Calendar型やInt, float型をサポートしているようです。

ドキュメントタイプはリストやマップを保持出来、32階層まで深くすることができます。Listの長さの上限はないですが1つのアイテムサイズの上限が400KBまでなのでデータの増え方を考慮した設計が必要になりそうです。

リストには異なる型の値を入れることが出来ます([1, “2”, “three”])。

マップは順不同のキー、バリューを保持します。こちらもリスト同様異なる型の値を入れることが可能です。

セットは順不同の単一の型のユニークな値を保持します。こちらもアイテムサイズ400KBまでの上限があります。

読み取り整合性

参考: Read Consistency

DynamoDBは複数のリージョンで利用できますが、それぞれのリージョンは独立していて別物になります。同じ名前で異なるリージョンにテーブルを作成してもそれらは完全に別のテーブルとみなされます。

それぞれのリージョンには複数のアベイラビリティゾーンがあり低遅延のネットワークでつながっています。DynamoDBのテーブルへの書き込みが完了すると1秒以下ですべてのストレージに伝搬されます。

DynamoDBでは結果整合性と強整合性読み取りがサポートされています。

ただし強整合性読み取りはレイテンシーが高く、ネットワーク遅延によりエラーになりやすいようです。またセカンダリインデックスもサポートされません。

読み取り書き込みキャパシティモード

参考: Read/Write Capacity Mode

使った分だけ支払うOn-Demand ModeとコストコントロールできるProvisioned Modeの2つがあります。

On-Demand ModeではRequest Unitsという単位でスループットが定義されていて操作やデータのサイズによってどのくらい消費されるかが決まります。自動で前回のピークの倍の量のスループットが確保されるような仕組みになっています。

Provisioned ModeはCapacity unitという単位でキャパシティが定義されていてこちらも操作やデータのサイズによってどのくらい消費されるかが決まります。自身でスループットを指定してコストを予測できるようになっています。

また、これらは24時間に一度切り替えられるようです。





ということで概要は抑えたかな。