AWS / SAP-C02

SAP-C02-179 · セクション 20 / タスク 4.4

Purpose-built DatabaseへのModernization

Amazon DynamoDB / Aurora Serverless / Amazon ElastiCache / Relational / Key-value / Cache / Access Pattern

既存アプリケーションでは、長年の機能追加によって、1つのリレーショナルデータベースが異なる性質の処理をすべて引き受けていることがあります。

例えば、

業務データベース
│
├─ 注文
│   └─ 結合 / トランザクション
│
├─ セッション
│   └─ session_idで取得・更新
│
└─ 商品表示用集計
    └─ 同じ結果を大量に反復参照

という構成です。

目的別データベースへのモダナイゼーションでは、すでに学習した各データストアの特性を前提として、

1つのデータベースに
異なるAccess Patternが混在していないか
        ↓
どの責任は残すか
どの責任は切り出せるか
        ↓
分離による効果は
追加される複雑性を上回るか

を判断します。

1. データベース単位ではなくAccess Pattern単位で分解する

現在、

アプリケーション
        ↓
1つのRDB

という構成だからといって、すべての処理が同じデータモデルを必要としているとは限りません。

例えば同じRDB内でも、

注文
→ Relationalな関係とトランザクションが必要

セッション
→ session_idによる独立した取得・更新

商品表示
→ 同じ読み取り結果を大量に再利用

という違いがあります。

ここでの目的は各Access Patternを改めて分類することではなく、現在1つにまとめられている責任の中から独立して移せる部分を発見することです。

2. 実際の利用関係から切り出し候補を作る

テーブル単位で、

このテーブルはDynamoDB
このテーブルはAurora

と先に決めるのではありません。

確認するのは、

どの処理から利用されるか
他のデータと結合されるか
同じトランザクションに含まれるか
独立して変更できるか
同じ結果を何度も読み取っているか

です。

例えば、

セッション
↓
session_idで取得・更新
↓
注文データとは独立

なら切り出し候補になります。

一方、

注文更新
+
ポイント更新
↓
同じトランザクション

なら、単純なテーブル移動だけでは責任を分離できません。

3. 「データベース全体を移す」前提を外す

目的別データベースへのモダナイゼーションでは、

現在のRDB
↓
全部を別サービスへ移行

とは限りません。

例えば、

現在

1つのRDB
├─ 注文
├─ セッション
└─ 商品表示

から、

注文
→ Relationalとして残す

セッション
→ Key-value責任として分離

商品表示
→ Cacheを追加

のように、必要な部分だけを切り出せます。

重要なのは、データベース製品を置き換えることではなく、異なるAccess Patternを適切な責任境界へ分けることです。

4. Relationalとして残す責任を明確にする

既存RDBの中でも、結合、トランザクション、リレーショナルな関係が業務上必要な部分は、Relationalとして残す候補です。

例えば、

注文
+
注文明細
+
支払い情報

を一連の処理として扱う必要があるなら、その責任まで無理にKey-valueへ変える必要はありません。

目的別データベース化では、切り出せる部分だけを分離し、残すべきRelational責任は残すという判断が重要です。

5. Relationalを残したまま運用責任だけ変えられるか確認する

RelationalなAccess Pattern自体は維持したい一方で、

負荷増加前に容量変更
↓
イベント終了後に容量を戻す

という容量運用を継続している場合があります。

この場合は、データモデルまで変更するのではなく、

Relational責任
→ 維持

容量調整責任
→ 減らせるか評価

という分離を考えます。

その候補としてAurora Serverlessを利用できる場合があります。

ここでの判断対象はAurora Serverlessの機能そのものではなく、既存RDBに残す責任と運用から外せる責任を分けることです。

6. 独立したKey-value責任だけを切り出す

既存RDBの一部が、

session_id
→ セッション状態

のような独立したKey-value Access Patternであり、

他テーブルとの結合なし
同一トランザクションなし
独立して変更可能

であれば、その責任だけをAmazon DynamoDBへ分離できる可能性があります。

重要なのは、キーで取得していることだけではありません。既存の業務トランザクションから本当に独立しているかまで確認します。

7. キーアクセスでもトランザクション境界が残るなら即分離しない

例えば会員情報が、

user_id
→ 会員情報

で取得されていても、

注文作成
+
ポイント残高更新
↓
現在は同一DBトランザクション

になっている場合があります。

ここで会員情報だけを別データストアへ移すと、

注文DB
+
別データストア

にまたがる処理へ変わります。

したがって、

Key-valueに見える
↓
即DynamoDB

ではなく、

現在のトランザクション境界を確認
        ↓
独立した責任へ分離できるか
        ↓
できる
        ↓
Amazon DynamoDBを評価

という順序で判断します。

8. Cacheとして外せる読み取り責任を探す

既存RDBへのアクセスの中には、同じ結果を大量に繰り返し取得している処理があります。

その読み取りが、

一定の古さを許容できる
+
同じ結果を再利用できる

のであれば、正規データの保存責任を移さずに、読み取りだけをCacheへ分離できます。

例えば、

正規の商品データ
→ 既存データストア

高頻度の商品表示
→ Amazon ElastiCache

という構成です。

9. Cacheでは正規データの所有責任を変えない

Amazon ElastiCacheを追加する場合でも、正規データの所有元までCacheへ変更する必要はありません。

目的は、

毎回元データストアへ到達する読み取り
↓
再利用可能な結果はCacheから取得

へ変えることです。

したがって、正規データの所有と反復読み取りの高速化を別の責任として扱います。

10. 分離による効果と追加される複雑性を比較する

Purpose-built Databaseを利用できるからといって、分離できるものはすべて分離するとは判断しません。

新しいデータストアを追加すれば、

監視
権限管理
障害切り分け
データ同期
変更管理

などの責任も増えます。

そのため、

現在の問題
        ↓
分離による効果
        ↓
追加される運用・設計の複雑性

を比較します。

例えば、

利用頻度が低い
+
現在のDB負荷への影響も小さい
+
切り出すと同期処理が増える

のであれば、Purpose-built Databaseへ分離しない判断もあり得ます。

11. 分離前に依存関係を確認する

切り出し候補が見つかったら、そのデータは本当に独立して変更できるかを確認します。

主な確認対象は、

結合
同一トランザクション
更新順序
正規データの所有元
他処理との依存関係

です。

例えばセッション状態が業務データから独立していれば、Key-value責任として分離しやすくなります。

一方、

注文確定
+
ポイント残高更新

を現在1つのトランザクションとして保証しているなら、その境界を無視して切り出すことはできません。

12. 効果と独立性の高い部分から段階的にModernizeする

複数の切り出し候補が見つかっても、

全テーブル
↓
一括再設計

する必要はありません。

例えば、

第1段階
高頻度で再利用される読み取りへCacheを追加

第2段階
独立したセッション状態をKey-valueへ分離

第3段階
残ったRelational処理の容量運用を見直す

のように進められます。

先に、

依存が少ない
+
効果を確認しやすい

部分から変更すれば、既存システム全体を一度に再設計する必要を減らせます。

一方、効果が小さく依存関係が大きい処理は、無理に初期段階で切り出す必要はありません。

13. 同じアプリケーションで複数のデータストアを使う

モダナイゼーション後は、例えば次のような構成になります。

アプリケーション
│
├─ 注文処理
│      ↓
│  Aurora Serverless
│  Relational
│
├─ セッション
│      ↓
│  Amazon DynamoDB
│  Key-value
│
└─ 商品表示
       ↓
   Amazon ElastiCache
   Cache
       ↓
   正規データストア

重要なのは、複数サービスを導入したことではなく、1つのデータベースに混在していた異なる責任を分離したことです。

14. モダナイゼーション判断表

既存の状態検討する変更
1つのRDBに異なるAccess Patternが混在責任単位へ分解
Relationalな関係・トランザクションが必要その責任はRelationalとして残す
Relationalは必要だが容量調整を手動運用Aurora Serverlessで運用責任を減らせるか評価
独立したKey-value Access PatternがあるAmazon DynamoDBへの切り出しを評価
キーアクセスだが他データと同一トランザクション先に責任境界を分離できるか確認
同じ読み取り結果を大量に再利用Amazon ElastiCacheによるCacheを評価
分離効果より追加複雑性が大きい無理に分離しない
複数の切り出し候補がある独立性と効果の高い部分から段階的に進める

15. 判断フロー

既存データベースを確認
        ↓
Access Patternごとに
責任を分解
        ↓
その責任は
他のデータから独立しているか
        ↓
いいえ
        ↓
既存境界を維持するか
先に責任境界を分離

独立している場合は、

Relational責任か
Key-value責任か
Cache可能な読み取りか
        ↓
適切なデータストアを評価

さらに、

分離による効果
        ↓
追加される複雑性
        ↓
効果が十分か
        ↓
はい
        ↓
独立性・効果の高い部分から
段階的にModernize

と進めます。

最終的には、

単一RDB
↓
Access Patternを発見
↓
依存関係を確認
↓
残す責任と切り出す責任を決定
↓
効果と複雑性を比較
↓
必要な部分だけ段階的に分離

という順序で判断します。