DynamoDBのメモ書き+使ってみた雑感

Amazon DynamoDBを使う機会があったので
メモ書きと雑感を書き残してみます。
なんか間違ってたらツッコミ欲しいです。


Amazon DynamoDBとは

ざっくりと噛み砕いて説明すると
SSDでめちゃ速くて勝手にスケールしてくれるKVS」
ですかね。
詳しくは公式ドキュメントを。
http://aws.amazon.com/jp/dynamodb/#access_model_api_overview

DynamoDBのデータ構造

DynamoDBは「テーブル単位」で管理します。
最初にテーブル名/主キー名/スループットなどを決定してテーブルを作成します。
Rowデータには連想配列っぽい感じでなんでも入れられます。スキーマレスってやつですね。
また、格納できるデータ型については「数値型」「文字型」です。

テーブルキーのアクセスモデル

DynamoDBではテーブルを作成するときにアクセスモデルを2つの中から選びます。
「プライマリーキー方式」と「コンポジット(ハッシュ+レンジ)方式」です。

プライマリーキー方式

一意となるハッシュキーを1つだけ決める方式。通常のKVSっぽい感じですかね。

コンポジット方式

2つの複合キーを決定します。その組み合わせで一意になるようなデータ構造です。
1つはハッシュキー、もう一つはレンジキーを設定します。
以下、ドキュメントからの引用です。

例えば、「UserID」(ハッシュ属性、複数のサーバーにわたる負荷のパーティション化に使用)と「Time」(範囲属性)で構成される複合プライマリ キーを持つ「Status Updates」テーブルがあるとします。クエリを実行すると、1)UserID 値と Time 値の組み合わせによって識別される特定の項目、2)特定のハッシュ「バケット」(この場合は UserID)のすべての項目、3)特定の時間範囲内にある特定の UserID のすべての項目のいずれかを取得できます。「Time」に対する範囲クエリは、UserID ハッシュバケットが指定されている場合にのみサポートされます。

http://aws.amazon.com/jp/dynamodb/

API

テーブル操作(みればわかるので説明は省略)
  • CreateTable
  • UpdateTable
  • DeleteTable
  • DescribeTables
アイテム操作

PutItemとUpdateItemの違いがよくわかってない。(どっちも追加/更新できるようだし)

  • PutItem
  • UpdateItem
  • DeleteItem
  • GetItem
バッチ操作

1回のリクエストで複数の読み込み/書き込みを行える。

  • BatchGetItem
  • BatchWriteItem
クエリ操作
  • Query

コンポジットテーブルのみ利用可能。
レンジキーでの比較演算( < > <= >= )やBetween検索などが行える。

完全スキャン
  • Scan

単純な検索。値に対しても絞込みを行えるが、
完全スキャンでありインデックスは使われないので
あまり大きいデータにはつかわないほうがよさそう。
いくつか制限もある。

料金について

課金対象は以下の項目です。

スループット保証について補足

なかなかめずらしい課金方式ですね。
要は「1秒間あたりのスループットを予約しておきますよー」という計算方式です。
1秒間辺りのアクセス数がわかればそんなに難しくないかなとも思いますが、
ユニットという単位に注意。やり取りするデータの容量(1KB単位)で料金が変わります。
容量が1KB以下であれば「1ユニット=1アクセス」という計算でOK。
ユニットの詳細はこちら。
http://aws.amazon.com/jp/dynamodb/faqs/#What_is_a_read/write_capacity_unit_How_do_I_estimate_how_many_read_and_write_capacity_units_I_need_for_my_application

また「整合性のある読み込み」を選択していると読み込み回数が2倍になるようです。
整合性モデルについてはこちら。
http://aws.amazon.com/jp/dynamodb/faqs/#What_is_the_consistency_model_of_Amazon_DynamoDB

雑感:良いと思った所

メンテンナンス(スケール)いらず

これは本当に大きい。これだけで使う価値あり。*1

スケールアップ/スケールダウンがオンラインで可能

updateTableコマンドで閾値をオンラインで操作することができます*2
特にスケールダウンできるのはかなり良いですね。
ただしスケールダウンに関しては1日1回のみ、という制限があるらしいです。*3
また上げ幅と下げ幅が決められているので注意が必要。*4

タダでつかえる範囲がある。

以下の条件を満たしていれば無料でDynamoDBが使えるらしい!
個人ユースでも安心ですね。

  • データ容量100M未満
  • 読み込み10ユニット/秒
  • 書き込み5ユニット/秒
EMR連携

ElasticMapReduceと連携してDynamoDBのデータを集計できるのは夢広がりますね。
Hiveでゴニョゴニョすれば良いようです。

手順は以下参照。
http://docs.amazonwebservices.com/amazondynamodb/latest/developerguide/EMRforDynamoDB.html
しかしこれ料金はどうなるんだろう?EMR分だけで済むのかな?

雑感:微妙と思った点

テーブル毎の課金?

テーブル毎にスループットを設定できるということは、テーブル毎に料金がかかるということですかね。
テーブルたくさん作ると料金が大変なことになるかもしれませんね…

BatchGetItemsについて

BatchGetItems(BatchWriteItems)は1回のリクエストで複数キーを取得できるのですが、
内部的には複数キー分のユニットを消費してしまいます。


以下はテストしてる時に気付きました。
まず30個のkeyをBatchGetItemsに投げます。
そして期待している結果としては5件ヒットする、としましょう。
その時、取得結果が「毎回違う」という現象が発生しました。
これは単純にReadスループットを10ユニットに設定していたため、
20のキーが予約分から漏れてしまっていたということです。
つまり複数キーを一度に取りたい要件がある場合にはその回数分も考慮する必要があります。

スループットを超えるとリクエストが無視される

また上記の現象からわかるのですが、
スループットから漏れたリクエストは無視されるようです。
これを回避するには「余裕をもってスループットを設定する」しかないでしょう。
幸いにも閾値によるアラート機能があるのでこれを使って
自動で常に実スループットを上回る設定をしておく仕組みを入れておくとよいかもしれませんね。
ただしご利用は計画的に。

  • 似たような問題のスレッド

https://forums.aws.amazon.com/thread.jspa?threadID=93339

まとめ

DynamoDBは利点も多く、使い方を間違えなければとても有用だと思います。
特性を十分考慮した上で導入を検討するのが良いでしょう。

参考資料

アーキテクチャや実際運用した時の料金などが参考になります。
http://www.slideshare.net/AmazonWebServicesJapan/20120409-aws-meisterreloadeddynamodb-12509631

*1:AWSを100%信頼するという前提です

*2:プロダクトでは試したことがないので「できるらしい」にしておこうかな…

*3:最新バージョンはこの制限ありません

*4:スループットを10->1000とかには設定できない