CQRSとDynamoDBのデータ構造設計
先日、結婚しました。エンジニアの内山です。
今回は DynamoDB におけるデータ構造設計に関する考察を行いました。
概要
DynamoDB のデータ構造設計を行う際、RDB の設計とは異なる考え方をしなければなりません。
DynamoDB は、NoSQL であり、様々な制約があるので、色々と頭をひねる必要があり、四苦八苦しながら何とか形にしています。
そんな中、CQRS という考え方があることを知ったので、DynamoDB のデータ構造設計との関係性についてまとめてみました。
CQRSとは
__CQRS は「Command Query Responsibility Segregation:コマンドクエリ責任分離」__という意味で、DBへの書き込み( Command )と読み込み( Query )を別物として捉える考え方です。書き込み用と読み込み用のそれぞれの DB を分離するイメージですね。
RDBのリードレプリカに似ています。
リードレプリカでは、書き込み用 DB (マスター)と読み込み用 DB (スレーブ)があります。マスターとスレーブではデータ構造(スキーマ)は完全に同じです。
CQRS では、書き込み用と読み込み用でデータ構造が異なっていることを許容していると言えます。
DynamoDB での Command 用データ構造
DynamoDB には、以下のような特性があります。
- トランザクション機能はあるが制限がある
- 同時に10レコードまで。意外と超えてしまうことが多いので注意が必要
- トランザクション内でのレコード更新はアトミック性がある
この特性を考慮すると、Command 用データ構造を設計する場合、
アトミック性を保持したいデータは、限られたトランザクション内に収められるようなデータ構造にしておく必要があります。
DynamoDB での Query 用データ構造
また DynamoDB には、以下のような特性もあります。
- 1テーブルにつき作成できるインデックス数が限られている( GSI は20個、LSI 5個まで)
- ソートするカラムはインデックスが貼られている必要がある( RangeKey )
これらの制約を考慮し、データの取得パターンに応じて、最適なデータ構造( Query 用データ構造)を作っておく必要があります。
例えば、以下のようなアクセスパターンがあるでしょうか。
- ソート/検索/ページネーションを行い、データの一覧を取得する
- グループに所属しているユーザー数を取得する(あらかじめ集計しておくなど)
Query 用の DB は DynamoDB に限らず、ElasticSearchを用いても良い場合もありそうです。
CommandデータからQueryデータへの変換について
__Command データから Query データを作成する必要があります。__これは例えば DynamoDB Stream 経由で、Lambda を実行して行うのが良さそうです。作成失敗した時は Lambda が再試行するので、ほぼ変換は成功させることができます。
その他の考察
どうしても厳密なトランザクション処理を行う必要がある場合は、Kinesis 経由で RDB を用いてデータを更新することも可能だと思います(Command)。
更新が成功したら、DynamoDB や ElasticSearch に Query 用データを作成することができます。
参考
【AWS re:Invent 2017 レポート】サーバレスアプリケーションのデータレイヤーの最適化 #SRV301
CQRSとイベントソーシングの使用法、または「CRUDに何か問題でも?」
DynamoDBデータモデリング虎の巻:第壱巻 〜前提知識編〜