[書評]Monolith to Microservices 3章
の続編
4章はDecomposing the Database
どうやってDBを分割するかという話
・共有データベース
どのサービスがどのカラムを使ってるか不明なので分かりにくい
また、誰がデータをコントロールしてるかわからない
・共有データーベースを解消するには
1.Viewを使って各々のサービス向けにする
最善じゃないが何を公開して何を隠すか決めることができる
2.APIでラップする
・READ用のDBを公開する
大量のデータをselectするためにRead用のDBを公開する
あくまでRead用
何かしらの方法で既存のDBからマッピングする
例えば、バッチで定期的にコピーやMySQLのViewを使う
・DBの移行方法
二つのDBにアプリケーションから両方書き込みする
新しいDBで読み書きをし、古いDBは書き込みだけ
移行に失敗したら戻せば良い
・DBとコードどちらを先に分割するか
パフォーマンスの懸念がある場合はDBを先に分割する
この懸念がなければコードから分割する
両方一緒に分割するのはビックバンになるので避けるべき
・レポジトリーパターン
最初にレポジトリークラスをテーブルごとに各々作る
コードの可読性がよくなるので良い方針
・モノリシックをデータアクセスレイヤーにする
モノリシックにそのままAPIつける
こうすることで新規サービスはステートレスになる
・DBを分割した場合のjoin
joinできなくなるので自分が管理してるDBからデータを引いた後に
別サービスのDBを参照するためにAPIを叩いて擬似的にjoinする
パフォーマンスが悪くなるのが目に見えるけど
思ったほど悪くならないのではとのこと
・DBを分割した場合のデータ一貫性
むしろこっちの方が問題
A DBのレコードを削除した場合
A DBにはないけど、B DBにはデータが存在していてjoinできないみたいな問題が起こる
DBが一つならlock使ってdeleteしてるから問題ないんだけど
この場合はアイデアとしてAPIリクエスト時にデータがなかったら410を返却し
表示側どうにかして整形する
あるいはイベントを講読して頑張って消す
・静的データ
静的データをマイクロサービス化するなら
データのコピーを各々のサービスに持たせる
あるサービスは利用するけど別サービスは利用しない国コードみたいなのがあると
DBが一箇所だと全部のサービスが国コードを利用することになる
また、データ量が少ないならライブラリとして配布してもよい
こちらの場合は全部のサービスが同じ国コードを利用するには
全サービスの全ライブラリをアップデートする必要があるという問題もある
・トランザクション
そして最大の問題がこれw
DBが別なのでトランザクションが発行できない・・・
・2phaseコミット
マイクロサービスで利用できるトランザクションとして2phaseコミットがある
すべてのサービスにSQLを実行できるか聞く
すべてのサービスがOKと言ったらSQLを実行する
これだけ聞けばダメなのわかるよねwwww
・トランザクション+マイクロサービス
トランザクションを利用するDBは分割しない
・Saga
ロックなしでマイクロサービス協調する仕組み
SQLを一個ずつ実行し、途中でエラーになったら
一個ずつ全部ロールバックするSQLを発行する
またSQLを失敗したらその処理を最後に回す
これもこれで問題ありそうだけど・・・
・相関ID
マイクロサービスで同じイベントで処理された一連の処理を関連づけるもの
長くなるので続くよ