DynamoDB使ったり調べたまとめ (2017Early)
書くこと
サ〜バ〜レスな構成にお安く気軽なデータストアが欲しかったのでちょっと調べた。
世間的にはDynamoDBを割と併用してるっぽいので。
1.小規模用途で安いデータストアが欲しいだけ
初期コスト以外の要素をあまり気にしない方向で考える場合。
基本
- 最小は1読みキャパ/1書きキャパで約0.6$ / 月
- でもアカウントごとに無料枠は25ユニット無料
- この確保量が月額かかるので別に使用量従属課金というわけでは全然ない
読み込み
Get
- まあKVSなので、基本はユニークなHashKeyのみでアクセスできるようにする
- プライマリキーはHashKey(順不同),かHashKey + RangeKey(範囲指定、Sort可)から成る
- ユーザーごとに独立してるデータとか。
- indexは グローバルセカンダリインデックスと HashKeyに従属するローカルセカンダリインデックスがある。
- 安く済ませたいならグローバルセカンダリインデックス(ユニークキーを含まないindex)は諦めろ
Scan、Query
- 小規模ってわかってるなら理性捨ててScan(index全件取得)するのもあり
- 読み込み時に強い読み込み整合性モードを使えば、直前の書き込み全て反映されたレコードとして取得できる、(ただしRCU消費2倍)
- 範囲指定やソートができるのはRange Keyのみ。
- 基本検索はそこまで強くないと思っておく
書き込み
- 普通に update column += 1 とか使える (これと先の”強い整合性”があるだけでもS3にJSON突っ込んでデータストア代わりにするのと話は違ってそれなりに意味はある気がする。)
- 条件付きアップデートも可能
- レコード間でのトランザクションはもちろん保証されない
- 特に複数テーブル書き込みに関してはオレオレトランザクション化要るので基本諦めろ
2.大規模用途での可用性や整合性の担保についてメモ
読み込み
Get
- 基本はこっちでもユニークなキーのみでのget,シンプルなKVSとしての利用にすることを心がける
- HASH KEY(の頭文字)は散らす。データサイズがでかくなるとHASH KEYをもとに自動でパーティションが切られるから。
- グローバルセカンダリインデックス多用しそう。この場合インデックスごとにキャパシティユニット設定する。
- データサイズは小さくしよう。
Scan , Queryについて
- Scanはセカンダリインデックス全件取得、QueryはRangeKeyやIndexの内容に従って走査する
- 1度のレコード取得クエリに対してデータが1MB上限あるので、テーブルがでかくなると一度にScanできない可能性はある
- LIMITやフィルタ機能はRCU消費を何ら抑えることはできない,あくまでSQLのWHERE文的にクエリ書きやすくなるだけっぽい
- Queryはともかく特に大規模用途だとScanは使わないに越したことがない。
クエリキャッシュ
- 同じテーブルが参照されまくるとRCU消費するのでElastiCacheとか前に置いてるケースを散見。結局そうなるんか。
書き込み
DynamoDB ベストプラクティス 参考にした
DynamoDBでのポイントまとめ
複数テーブル同時更新
- テーブル分割時、複数テーブル書き込み必要な時は自前でACID整備することとなる。NoSQL…
- 更新依頼書テーブル的な実装/タスクキュー的な実装の上でupdateという形をとる(辛そう)
- スループット確保のためどうしてもテーブル分けたり非正規化しなければ場面も出てくるので、全く触れなくて済むというわけでもないかも????
- DynamoDB Stream も使えるそう。
同じレコード(というよりテーブル)に対する大量のupdate
- 同じレコードに同時に大量にincrement指定がくるような場合、そのパーティションのスループットが非常に下がる。
- ここでも更新リクエストをタスクキュー的に実装しておいて、読み込み時にそれらをSUMするか、1つのレコードにまとめる実装をする必要がある。
感想
- 単なるKVS以上の何かを求め始めた場合、結構留意することありそう。(うまい話はない)
- トランザクションって素敵だね…
- 他のNoSQLとしてAWS SimpleDBってのもあったけど死んでしまったの?
- GCP周りのサービスも調べたい