前置き
先日、業後にソフトウェアアーキテクチャハードパーツの第6章である
『業務データの分解』についてワークショップを開催しました。
この章の内容は、ごく一般のモノリスおよびモジュラーモノリスのように、
サービスというプロセス観点では、コンテキスト境界が切り分けられているのにもかかわらず、
データベース自体は物理的に1つで繋がっている場合、
つまりアーキテクチャ量子としては1つであるがゆえに、発生する問題点を解決するための
DBの分解の動機と、DBを分解することで生じるリスクの
大きく分けて2つの観点からの考察がなされている。
前提知識
アーキテクチャ量子
モジュラーモノリスのように、プロセス観点だけコンテキスト境界を定義して、
モジュール同士を疎結合にしていたとしても、
DBが物理的に1つでそこで結合していた場合、それはアーキテクチャ量子としては1つ。
つまりマイクロサービスではない。
マイクロサービスは、DBまでもが【物理的】にも完全に分離されており、
デプロイ時とかに他のサービスコンテキストに影響を与えない。
この物理的にっていうのがポイントで、1つのDB内で論理的に分離されているだけでは、
それはまだマイクロサービスとはいえない。
規模感とマイクロサービス
サービスというプロセス観点のコンテキスト境界のみを考えて分割した状態が、
モジュラーモノリスと呼ばれたもの。
この状態はアーキテクチャ量子1つであり、
小規模な組織で開発している小規模なシステムとかであれば、
わざわざマイクロサービス化するまでもない というか、
逆にマイクロサービス化することによって生じるデメリットが上回る可能性が高い。
データドメイン
しかし仮に、組織が巨大化してきて、システムも巨大化してきた場合には、
マイクロサービス化する恩恵が上回る可能性が高くなってくる。
その際に、プロセス観点のコンテキスト境界の考え方と同様にして、
データ観点のコンテキスト境界である【データドメイン】についての考察もした上で、
適切な大きさのアーキテクチャ量子を定義しなくてはならない。
プロセス観点のプログラムであるクラスがDBのテーブルに対応するなら、
コンポーネントがデータドメインに相当する。
要は関係性、意味の強い結びつきで集められたテーブルの集合のこと。
当然だけども、密に結合しているべきテーブル同士を無理にコンテキスト境界わけるメリットはほぼない。
モノリス構造のデメリット
最初にモノリスでシステムを構築する際には、
まあ大体データベースはRDBを使う方が汎用的であるし、望ましいと考えられるが、
マイクロサービス化の必要性が出てくるくらいの規模感になってくると、
徐々に
ワークショップ開始前に各々付箋にメモ

今回新たにシノニムという初めて聞くワードや、
汎用的なRDB以外のデータベースの選択肢、
さらには逆コンウェイ法則交えた組織的なデータマネジメント体制、
といった内容が事前に列挙された。
単一量子のデメリット
耐障害性
他には、仮にDBを分割していくと決めた際に
デプロイ自体のコストや何かしらDBに障害が発生した際に、サービス全体がその影響を受けてしまうこと。
他にはDB上のテーブルXというものをモジュールA、B、Eが使っていたとした場合、
この程度の量のモジュールならいいけども、
これがモジュール数がもっと大量になってきたら、どのモジュールがテーブルXを使用しているのか?
の特定がそもそも時間かかるし、ここで仮にモジュールEも実はテーブルXを使っているのに
忘れてました💦 なんてことになったら、
その間モジュールEの部分のプログラムは動かないって事態を招きかねない。

特性に応じたカスタマイズができない
たとえばあるデータドメインに関しては、整合性が非常に重視されるけども、
あっちのデータドメインに関しては整合性よりも可用性が強く求められるとか。
こんな風にデータドメインごとに異なる品質特性に応じて、
データベースの種別を変えるなんていうカスタマイズができない。
議論していて出た話題
ナチュラルキーでなくサロゲートキーでテーブル設計
一番最初のモノリスで構築する際の主キーの定義でサロゲートキーにした方が後々いいのでは? という話題が出ました。
というのも、たとえば超簡単な例で顧客が商品を注文 ていうビジネスのテーブル
を想定してみましょう。
仮に注文テーブルの主キーの設計を
商品IDと顧客IDという2つの外部キーからなる複合キーにしてしまった場合、
非常に密に商品テーブルや顧客テーブルと結合していることになります。
ここにもしも、注文明細ってテーブルがあったら、
注文テーブルと注文明細テーブルは同じコンテキスト内にまとめられているべき
意味合いの強いものであるため
これでは、いざDBを分割するために外部キー制約を外したい!ってなった際の
労力の大変さがすさまじいことは容易に想像つきます。
そこで極力最初から同じデータドメインにまとめられるべきでない
注文テーブルと 顧客テーブルのようなものに関しては、
ナチュラルキーによってテーブル同士が強い結合にならないように
最初からサロゲートキーでキー設定をしておく方が望ましいよね?
っていうディスカッションを行うことができ、これは個人収穫でもデカかったです。
データ統合要因
確かにデータベースを物理的にも分割することで得られる恩恵もある一方で、
当然【銀の弾丸】ではないのでデメリットもある。
それが以下の2つ。
手間がかかる
モノリシックなデータベースの場合には、データ整合性のために外部キー制約などを貼っていたけども、
それを外していく作業をして
→リスク抑えるため論理的にデータを分割
→物理的にも分割
というようにめちゃくちゃ手間がかかる。
ACID特性問題
単一量子のデータベース構造の時には、
単一のトランザクション処理が失敗した際に、ロールバックすることで
途中までの処理をなかったことにできたけども、
データが論理的・物理的に分かれている際には、この単一トランザクションというのが
できなくなってしまう。
そのためテーブルAとテーブルB両方に本来はレコードが追加されるという
トランザクションであった際に、
ACID特性が保てないことによって、テーブルAにはレコード追加できているのに、
テーブルBには追加できていない みたいに一貫性・整合性を担保するのが困難になる。
以上の2つの統合要因を考えつつ、分割の観点のメリットが上回り、
今後もデータの統合が起きにくいと予想される際に
初めてデータも分割する選択を選ぶという手順を取るのが理想。
ただし、あくまでもアプリチームとデータベースチームが分断されていない組織構造であることが前提でないと、恩恵は不十分になると考えられる。
アンチパターン
身の回りのエンジニアさんにマイクロサービス化した際のアンチパターンについて、
何件か聞きまわった結果、皆さん同じようなアンチパターンを経験していた。
中には、せっかくマイクロサービスのブームに乗ってマイクロサービス化したのに、
それは結果的に分散モノリスアーキテクチャになってしまっており、
もとのモノリシックに戻すのに2年もかかってしまったというケースすらあった。
共通点をいくつか簡潔に残しておく。
・そもそもプロセス観点でのコンテキスト境界の理解が不十分であった
・データドメインの理解の不十分
・可逆性を意識してリスク抑えながら小さく分割という手順を取らなかった
・段階を経ずにデータベースまで物理的に分割してしまった
・マイクロサービス化するまでもない事例なのに、無理にマイクロサービス化していた
(組織構造を変えやすい土壌がまだなかったとかetc)
・分割要因の観点からのみの考察に偏りが起きていた
発見と課題
データの観点でのコンテキスト境界としてデータドメインというもの、
また事前にサロゲートキーにしておくことで、不必要なテーブル間同士の密結合を予防。
それによって、データベースも物理的に分割する際に、
キー制約などを削除したりする手間暇を少しでも楽にできることを議論できた。
しかしながら、マイクロサービス化する際の、組織的制約として
組織的なデータマネジメント体制が取れていないことには、
このデータドメインごとに分割して各コンテキスト内で固有の情報を所持し、
かつ組織横断的にデータの利活用ができるようにメッシュを張り巡らせた仕組みがない
ことには、データごと分割した恩恵は存分には発揮できなそうという予想。
あとは、そのテーブルの所有権をどのサービスに持たせるのか?という課題点がまだ残されている。
大事なことは、データベースの
・分割要因
・統合要因
・RDBしか使える者がいないなどの組織的制約
の観点から、データベースごと分割するかどうかの評価を行うこと。