Techtouch Developers Blog

テックタッチ株式会社の開発チームによるテックブログです

事業の成長にアラインするためにAWS DMSを活用してDB統合した話

バックエンドエンジニア兼万年ダイエッターの taisa です。毎朝子どもの幼稚園バス送りのついでに短距離ダッシュして運動してます。はたから見ると変な人ですが、バスを追っかけるようにダッシュすると幼稚園バスの子どもたちは喜んでくれます。

テックタッチは以前、マイクロサービスの切り直し後に DB 統合を実施しました。本記事では、テックタッチがどういったプロセスで DB 統合を実施したかを紹介します。また、AWS DMS を利用する際に気をつけるポイントについても合わせて紹介します。

マイクロサービス切り直し記事のおさらい

本題に入る前に、前提情報として前回のマイクロサービス切り直し記事をおさらいし、どういった状況から DB 統合を実施したかを確認します。

  • 初期の頃からマイクロサービスアーキテクチャを採用しているが、事業の成長とともに環境が変化しドメイン境界が初期の思想と変わってきたこともあり、サービスAとサービスBが疎結合ではなくなってきた
  • サービスA、BをくっつけてモジュールA、Bとし、モジュールA、Bから別ドメイン境界の main と reader へサービスを切り直した
  • 切り直した結果、サービスの独立性が高まりマイクロサービスの利点の多くを享受できるようになったものの DB はサービスA、B時代のままである

なぜ DB 統合したか

DB 統合した理由は下記となります。そもそもマイクロサービスの切り直しをする前の時点で見えていた課題ではありましたが、一つずつ解決していくしかなく、結果的にマイクロサービス切り直し→DB 統合の順となりました。

  • DB がサービスA、B時代のまま分かれているので DB 周りの開発効率がよくない
  • RDS のコストが余計にかかる

Before

元々サービスA用のデータベースA、サービスB用のデータベースBだったのが、マイクロサービスの切り直しをした結果、それぞれのサービスがデータベースAとデータベースBにアクセスする状態となりました。 DB統合前の図

After

サービスにあったデータベースの分かれ方をしていないのでまずは一つに!ということで下記構成とするために DB 統合しました。 DB統合後の図

DB 統合の前提条件

DB 統合するにあたり下記のような前提条件があり、これらをクリアするために AWS DMS を利用することにしました。

やりたいこと

  • 別々のスキーマから同一スキーマに DB を統合したい

制約

  • それぞれの DB に同じ名前のテーブル名が存在するので、テーブル名をリネームする必要がある

DB の特徴

  • Aurora のレプリケーション機能を利用しようとしたが、利用中のバージョン(Aurora MySQL 2.x)ではテーブル単位のレプリケーションができなかったため断念(MySQL のユーザー情報等範囲外の情報まで同期されるとコントロールが難しいため同期したくない)

サービスの特性

  • main サービス
    • 夜間メンテナンス可
  • reader サービス
    • 無停止でDB統合したい!

AWS DMS(Database Migration Service)とは

AWS DMS の公式ページには下記のように書かれています。

AWS DMS は、データベースと分析のワークロードを迅速かつ安全に、ダウンタイムを最小限に抑え、データ損失ゼロで AWS に移行するのを支援するマネージド移行およびレプリケーションサービスです。

様々なデータソースに対応していて、SOURCE に移行元の DB、TARGET に移行先の DB をセットし DMS インスタンスとつなぎレプリケーションを開始するだけでデータの同期ができます。 DMSについての参考図 参考:20210216 AWS Black Belt Online Seminar AWS Database Migration Service

どのように DB 統合したか

reader サービスを無停止で実施するために Phase を3段階に分けて統合しました。

Phase1:DMS でレプリケーションを開始する

SOURCE となるデータベースAの binlog を有効(詳しくはこちらを参照ください)にし、DMS でレプリケーションを開始します。DMS はスキーマ名やテーブル名のリネームをしながら同期することが簡単にできるのでとても便利です。 DB統合Phase1の図

Phase2:reader の DB コネクションをデータベースBに切り替える

レプリケーションが開始できたら、reader サービスの DB コネクションをデータベースBへ切り替えます。ここは前提条件にあったように無停止で切り替えました。 DB統合Phase2の図

Phase3:メンテナンスにて書き込みを止め、main サービスのデータベースAへの向き先をデータベースBに切り替える

最後に main サービスのみメンテナンスにしてSOURCEへの書き込みを止め、DMS のレプリケーションを停止し 、DB コネクションの向き先をデータベースBに切り替えます。 DB統合Phase3の図

これで無停止かつサービス影響を最小限に抑えた上でデータベースAをなくすことができました。実際にはコードベースや機能ベースの対応も多々あり、それらを一つずつクリアしながら検証・リハーサルを繰り返していったので、なかなか大変なプロセスではありましたが、その甲斐もあり問題なく DB 統合できました。表向きは何も変わってないですが、こういった改善は何も起こらないことがすばらしいことだと自賛しています。 DB統合後の図

今後の課題

DB 統合できた一方で、2つのマイクロサービスが1つの DB に依存していることや、それぞれのサービスに必要なデータ特性が明確になってきたので最適化したいなど、今後も改善する余地がまだまだあります。これからも適切に事業要求と既存システム制約を考慮しながらアップデートしていきたいと考えています。 今後の課題の図

続いて AWS DMS の話に入っていきます。

AWS DMS で気をつけるポイント

あまり使う機会がないけど AWS DMS ってどうなの?といった声を聞いたことがあります。ということで、DMS を利用するにあたり気をつけるポイントをいくつか取り上げて紹介します。詳しい使い方については公式ドキュメントをご参照ください。

DMS 設定について

まず DMS の構成については上記でも記載したように、DMS インスタンスを作成、SOURCE と TARGET に対象データベースを設定、レプリケーション開始、とするだけでシンプルです。ただしいざプロダクションで利用しようとすると様々な設定や制約があり、ドキュメントを読み込んで検証する必要がありそれなりに大変でした。 DMS設定についての図

ポイント1:外部キー制約やインデックスが同期されない

DMS はレプリケーション開始時に TARGET DB にテーブルが存在しない場合はテーブル作成から実行してくれますが、その場合外部キー制約やインデックスは同期されません。そのためこれらも含めたい場合は(やりたいことにもよりますが)、「ターゲットテーブル準備モード」で「ターゲット上のテーブルを削除」を選択せず、事前にターゲットDBへテーブルを作成しておくことをおすすめします。関連ドキュメントはこちらポイント1の図

ポイント2:Max LOB サイズを適切に設定しないとデータが切り捨てられる

LOB(Large Object)とは、データベースにおいて扱われる巨大なデータを指します(BLOB、CLOB、XLOB)。DMS の設定には「LOB 列設定」という項目がありパフォーマンスの観点から「制限付きLOBモード」が推奨されています。「制限付きLOBモード」を利用した場合、実際のデータが設定した最大 LOB サイズを超過すると切り捨てられてしまいます。そのため、利用する際は下記のような SQL で LOB カラムの最大値をチェックして設定するとよいと思います。関連ドキュメントはこちら

SELECT (MAX(LENGTH(column)/(1024)) as "Size in KB" FROM table_name;

ポイント2の図

ポイント3:同期先テーブルの LOB カラムは NOT NULL 制約があると同期失敗する

こちらも「制限付き LOB モード」の話(「完全 LOB モード」は検証していない)ですが、LOB カラムの同期処理は最初に NULL となりあとからデータが同期される動きとなるため、LOB カラムが NOT NULL 制約の場合同期に失敗します。そのため、LOB カラムが Nullable であるか事前に確認・対応しておく必要があります。関連ドキュメントはこちらポイント3の図

ポイント4:インスタンスのメモリはなかなか開放されない

DMS は、初回のフルロード時にメモリを使い、その後のレプリケーション中も少しずつメモリを使い続けますが、メモリ解放は DMS に依存するためコントロールできません。そのため、初回フルロード時のメモリ使用量と、レプリケーション期間を事前に確認した上でインスタンスサイズをを設定する必要があります。また、設定項目が細かく存在するのでやりたいことや実際のデータを元にチューニングすることも可能だと思います。関連ドキュメントはこちらポイント4の図

ポイント5:フルロード時の too many connections 発生に要注意

初回のフルロード時に並列にロードするテーブルの最大数のデフォルトは「8」です。開発環境は特にコネクション数が少ないことも多いと思いますが、検証段階でも too many connections が発生しがちです。本番環境においても DB コネクションを使い切るリスクがあるので事前にコネクション数をチェックしておく必要があります。テックタッチの今回のケースではフルロードの速度は重要でなかったので最大数を4に減らしました。 ポイント5の図

AWS DMS で気をつけるポイントまとめ

上記はあくまで一例で実際には設定項目が沢山あるのでチューニングでなんとかできる部分もあると思います。実際に利用する際は上記を少し気にしつつうまくチューニングしてやってみてください。

まとめ

事業の成長に合わせてサービスのアーキテクチャをアラインすべく今回このような手法をとりましたが、サービスのアーキテクチャに合わせた手法は様々だと思います。どうしても難しければアーキテクチャを変更するのも手ですし、DB も含めてアラインするために AWS DMS を使うのも手だと思います。稼働中のサービスに手を加えるのは大変ですが、似たような課題を持っている方に本記事が何かの役に立てれば幸いです。