MySQL Router: InnoDB Clusterの自動フェイルオーバーと障害耐性を実現する「要」

MySQL tutorial - IT technology blog
MySQL tutorial - IT technology blog

課題:午前2時の悪夢と手動対応の代償

次のシナリオを想像してみてください。午前2時、電話が鳴り止みません。監視システムが大量の500エラーを報告し、データベースへの接続が完全に途絶えています。急いで確認すると、MySQL InnoDB ClusterのPrimaryノードがI/Oのボトルネックによりフリーズしています。理論上、クラスターは別のノードを自動的にPrimaryとして選出するはずです。しかし、アプリケーションは依然として、ダウンした旧ノードのIPアドレスに無理に接続を試み続けています。

その結果、数十ものマイクロサービスの .env ファイルを新しいIPに書き換え、一つずつ再起動するという骨の折れる作業が発生します。クラスターを導入しているにもかかわらず、結局手動で対応しなければならない状況に強いフラストレーションを感じるでしょう。この問題は、アプリが単一のDBノードに直接接続していることに起因します。これを根本的に解決するには、インテリジェントな調整レイヤーである MySQL Router が必要です。

以前、私たちのシステムの users テーブルが2000万レコードを超えた際、スロークエリが多発するようになりました。インデックスやコードの最適化だけでは不十分です。インフラに自己修復(Self-healing)能力がなければ、メモリやディスクの故障が発生した瞬間に、それまでの最適化の努力はすべて水の泡となってしまいます。

コアコンセプト:MySQL Routerの役割とは?

MySQL Routerは、アプリケーションとInnoDB Clusterの間に立つ「航空管制塔」のような存在です。アプリ側に各ノードのIPアドレスのリストを覚えさせる代わりに、Routerの単一のアドレスを提供するだけで済みます。

  • Metadata Cache (自動認識): Routerは常にクラスターと接続し、ノードの状態を把握します。どのノードがPrimary (Read-Write) で、どのノードがSecondary (Read-Only) かを正確に認識します。
  • インテリジェントなルーティング: 書き込みクエリはRouterによってPrimaryノードへ直接送られます。一方、読み取りクエリはSecondaryノードに均等に分散され、メインノードの負荷を軽減します。
  • アプリへの透過性: DBノードに障害が発生すると、Routerは自動的にそのノードをルーティング対象から除外します。アプリケーション側はこの変更を意識する必要はなく、設定の修正や再起動も不要です。

実践:MySQL Routerのインストールと設定

通常、レイテンシを最小限(1ms未満)に抑えるため、MySQL Routerをアプリケーションサーバーと同じホストにインストールします。以下に実際の手順を示します。

1. クイックインストール

Ubuntu/Debianでは、公式のMySQLリポジトリを利用するだけです:

sudo apt-get update
sudo apt-get install mysql-router

CentOS/RHELを使用している場合も、コマンドは非常にシンプルです:

sudo yum install mysql-router

2. 自動初期化 (Bootstrap)

設定ファイルを手動で書くのはミスが起きやすいため避けましょう。--bootstrap コマンドを使用して、Routerにクラスターから必要な情報を自動的に取得させます。

mysqlrouter --bootstrap [email protected]:3306 --user mysqlrouter

引数の説明:

  • cluster_admin: クラスターの管理権限を持つアカウント。
  • 192.168.1.10:3306: クラスター内の稼働している任意のノードのIP。

パスワードの入力後、Routerは非常に重要な2つの接続ポートを開放します:

  • Port 6446: 書き込み優先 (Read-Write) ポート。常に現在のPrimaryノードを指します。
  • Port 6447: 読み取り優先 (Read-Only) ポート。Secondaryノード間で自動的に負荷分散を行います。

3. サービスの運用

システム起動時にRouterが常に実行されるよう、サービスを有効化します:

sudo systemctl start mysqlrouter
sudo systemctl enable mysqlrouter

4. アプリケーションの更新

最後のステップは、 .env ファイルの接続情報の変更です。データベースのIPを直接指定する代わりに、アプリと同じサーバーにRouterをインストールした場合はlocalhostを指定します。

# 旧設定 (ダウンタイムのリスクが高い)
DB_HOST=192.168.1.10
DB_PORT=3306

# 新設定 (自動フェイルオーバー対応)
DB_HOST=127.0.0.1
DB_PORT=6446

検証:障害発生時の挙動

安心を得るためには、障害のシミュレーションテストを行うべきです。現在のPrimaryノードで systemctl stop mysql を実行してMySQLサービスを停止させてみましょう。すぐにRouterのログを確認します:

tail -f /var/log/mysqlrouter/mysqlrouter.log

RouterがPrimaryのダウンを検知したことが確認できるはずです。クラスターが新しいリーダーを選出するのを待ち(通常10〜20秒)、その後Routerは自動的にメタデータを更新し、ポート 6446 からのすべての接続を新しいIPに転送します。システムは長時間ダウンすることなく、一瞬の瞬断のみで復旧します。

まとめ

MySQL Routerの使用は、単なる技術的な選択ではなく、「安心」を買うことでもあります。リソース消費も非常に少なく(通常は100MB RAM未満)、システムの安定性に対する投資としては非常に安価です。覚えておいてください。Routerのないクラスター構成は、ハイアベイラビリティ(高可用性)への道のりのまだ半分に過ぎません。

Share: