keshipi's blog

いつでも自分を振り返れるために書きます

データベース分解の手引き

https://www.oreilly.co.jp/books/9784814400065/

「ソフトウェアアーキテクチャ・ハードパーツ」を読んでいる。

マイクロサービス化を進めるにあたり、アプリケーションをサービス毎に分割したがデータベースの分割がなかなか進まないということは起こるのではないだろうか。まさに現職のシステムがこの状態にあたる。
十数年利用してきたデータベースには数百のテーブルが作成されており、なかなかドメイン毎に区切られたデータベースへの移行が進んでおらず、
単一データベースを複数のサービスで利用するサービスベースアーキテクチャと呼ばれる状態である。
最近ではデータベースが単一障害点(SPOF: Single Point Of Failure)となり、サービス全体に影響が波及してしまっている事案が頻発している。

この本の第6章にはモノリシックなデータベースをどのように分解し、サービス毎に作られたアプリケーションから利用できる状態にしていくか、という手引きが書かれている。
とても丁寧かつ分かりやすく記述されており、今後自分がデータベースを分解することがあるかもしれないのでその時のためにまとめておく。

データ分解要因

どのような場合にデータの分解を検討すべきか、という主な要因が6つ挙げられている。 1. 変更制御 - データベースに対して変更を加えたときにいくつのサービスが影響を受けるか 2. コネクション管理 - 複数の分散サービスから接続された場合に必要なコネクション数を処理できるか 3. スケーラビリティ - アクセスしてくるサービスの要求に応じてデータベースをスケールできるか 4. 耐障害性 - データベースのクラッシュやメンテナンスによるダウンタイムの影響を受けるサービスはいくつあるのか 5. アーキテクチャ量子 - 単一の共有データベースによって望ましくない範囲で単一のアーキテクチャ量子が形成されていないか 6. データベース種別の最適化 - 利用しているデータベースの種別は、そのデータを扱うのに最適か

アーキテクチャ量子 高度な機能的凝集、静的・動的結合を持つ、独立してデプロイ可能なアーティファクト

2と3に関してはAWSのRDSといったクラウドサービスを利用していれば比較的容易にスケールアウトできる。
現職ではこれらは大きな要因にならないのだが1と4がデータ分解を行う大きな要因になりうる。

別チームが運用するアプリケーションのためテーブルに加えた変更内容が、自分たちが運用するアプリケーションに影響を与えてしまうことが起こる。
影響範囲を確認するために時間をかけたコミュニケーションが必要になっていたりする。
また冒頭でも述べた通り、とある機能が利用しているテーブルへの高負荷が原因で、関連のない機能を提供する画面が利用できないといったことが起こっている。

データ分解プロセス

5つの段階を踏んでデータのまとまりを個別のデータベースへ移行していく。 5 process

Step1.テーブル毎にグループ化

それぞれのテーブルをデータドメイン毎にグループ化する。
ここでデータドメインとは、特定のドメインに関連し、限られた範囲の機能で頻繁に使用されるデータの集合を指す。

Step2.グループ毎にスキーマを割り当てる

グループ毎にスキーマを作成する。必ずしもスキーマとグループは1:1になるわけではない。
サービスは対応するグループとなるプライマリスキーマを使用するが、この段階ではスキーマ同士は結合されておりスキーマを跨いでテーブルの結合は行われる。
ただし、結合点がデータベース層からアプリケーション層へ移るので依存関係のチェックやコードの分析がIDEなどにより容易になる。 step2

Step3.スキーマ間のアクセスをサービスレベルで分離

各サービスの接続処理をリファクタリングし特定のスキーマに接続できるようにする。
そしてスキーマ間のアクセスはサービスレベルで解決できるようにする。
step3

Step4.スキーマを個別のデータベースに分離

それぞれのスキーマをデータベースレベルで独立させる。
サービスがスキーマ別にアクセスしている状態であっても、単一データベースにアクセスしているのであればスケーラビリティや耐障害性に悪影響を及ぼす可能性がある。
スキーマを別データベースに移す方法の選択肢は2つある。 - バックアップとリアストア - スキーマのバックアップを取得し、移行先のデータベースを準備したらスキーマをリストアしサービスの接続先を新しいデータベースのスキーマに変更する。そして元々のスキーマを削除する。 - 移行時にダウンタイムが必要になる。 - レプリケーション - 移行先のデータベースを準備したら、スキーマをレプリケートする。サービスの接続先を新しいデータベースのスキーマに変更する。そして元々のスキーマを削除する。 - ダウンタイムはなしで済む。 step4

Step5.サービスの接続先を変更

スキーマレプリケーションが完了したら、サービスが利用する接続先を変更して、元々のスキーマを削除する。 step5

データを分割することによるメリデメ

メリット

  • 他のサービスを気にすることなくチームでデータベースに対する変更を加えることができる。
  • ユースケースに最適なデータベース技術とデータベース種別を選択できる。

デメリット

  • サービスが大量のデータにアクセスする必要がある場合にパフォーマンスの問題が発生する。
  • 参照整合性が担保されないので、データの品質が低下する可能性がある。
  • 他のドメインに属するテーブルにアクセスするすべてのデータベースコード(ストアドや関数)はサービス層に移動する必要がある。