単一の MySQL データベースサーバーにはパフォーマンスの制限があり、単一障害点(SOPF)のリスクがあります。これは、業務システムの可用性を損なう可能性があります。複数の Elastic Compute Service(ECS)インスタンスを使用して高可用性 MySQL InnoDB Cluster を構築し、プロキシサービスを使用して柔軟なスケジューリングと読み書き分離を実現することで、データベースの可用性と耐障害性を向上させることができます。
アーキテクチャ
サービス クラスタを構築する場合、複数ゾーンにまたがる ECS インスタンスを使用すると、ビジネスのダウンタイムのリスクが軽減され、単一ゾーン障害に対する回復力が提供され、業務システムの安定性が向上します。
プロキシノード:クライアントリクエストを処理し、適切なデータベースノードに転送する役割を担います。プロキシノードは複数ゾーンにデプロイして、高可用性をさらに強化できます。
プライマリノード:クラスタのコアデータ処理ノードとして機能し、すべての書き込み操作を処理し、他のノードにデータを同期します。
セカンダリノード:プライマリノードからデータをレプリケートすることでデータ整合性を維持し、読み取り操作のみをサポートします。プライマリノードに障害が発生した場合、セカンダリノードから新しいプライマリノードが自動的に選出され、クラスタの継続的な動作が保証されます。
環境を準備する
4 つの ECS インスタンスを作成します。この例では、Alibaba Cloud Linux 3 を実行する ECS インスタンスが作成されます。
説明
インスタンス
インターネットアクセス
仮想プライベートクラウド (VPC)
vSwitch
IP アドレス
プロキシノード
ECS インスタンス A
インターネットアクセスが必要です。
MySQL をインストールした後、セキュリティを強化するためにインターネットアクセスを無効にします。
192.168.0.0/16
192.168.0.0/24
192.168.0.1
プライマリノード (読み書き)
ECS インスタンス B
192.168.1.0/24
192.168.1.1
セカンダリノード (読み取り専用)
ECS インスタンス C
192.168.2.0/24
192.168.2.1
セカンダリノード (読み取り専用)
ECS インスタンス D
192.168.2.2
ECS インスタンス B、C、および D に同じ MySQL バージョンをインストールします。この例では、MySQL 8.4 がインストールされています。 MySQL のインストール方法については、「Linux ECS インスタンスに MySQL データベースをデプロイする」をご参照ください。
手順
ステップ 1:クラスタノードを構成する
ECS インスタンス B、C、および D に接続します。詳細については、「Workbench を使用して SSH 経由で Linux インスタンスに接続する」をご参照ください。
ECS インスタンス B、C、および D に、同じユーザー名とパスワードを持つ同じ MySQL アカウントを作成します。
重要<username> は、作成する MySQL アカウントのユーザー名に置き換えます。
<password> は MySQL アカウントのパスワードに置き換えます。パスワードは 8 文字以上で、大文字、小文字、数字、特殊文字をそれぞれ 1 つ以上含める必要があります。
#次のコマンドを実行した後、ルートユーザーのパスワードを入力します。 sudo mysql -uroot -p \ -e "CREATE USER '<username>'@'%' IDENTIFIED BY '<password>';" \ -e "GRANT ALL PRIVILEGES ON *.* TO '<username>'@'%' WITH GRANT OPTION;" \ -e "FLUSH PRIVILEGES;"ECS インスタンス B、C、および D の
/etc/my.cnfMySQL 構成ファイルに次の内容を追加します。#ホスト名をノードの IP アドレスに設定します。 report_host=192.168.x.x #GTID 強整合性を有効にします。 enforce_gtid_consistency=ON gtid_mode=ON #ノードサービス ID を指定します。これは、各ノードに対して一意の正の整数である必要があります。 server_id=1 #各ノードの最大接続数を指定します。これは、すべてのノードで同じである必要があります。 max_connections=1024 #InnoDB 以外のストレージエンジンを無効にします。 disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"構成の変更を有効にするために、ECS インスタンス B、C、および D で MySQL サービスを再起動します。
sudo systemctl restart mysqld
ステップ 2:クラスタを作成する
ECS インスタンス A に接続します。詳細については、「Workbench を使用して SSH 経由で Linux インスタンスに接続する」をご参照ください。
ECS インスタンス A に mysql-shell と mysql-router をインストールします。
#公式 MySQL リポジトリを追加します。 sudo rpm -Uvh https://repo.mysql.com/mysql84-community-release-el8-1.noarch.rpm #mysql-shell と mysql-router をインストールします。 sudo dnf install -y mysql-shell mysql-router mysql-community-clientMySQL Shell を使用してプライマリノードに接続します。
<username>は、「手順 1:クラスタノードを構成する」で作成した MySQL アカウントのユーザー名に置き換え、<IP>はプライマリノードの IP アドレスに置き換えます。 MySQL アカウントのパスワードを入力し、プロンプトに従ってパスワードを保存するかどうかを選択します。パスワードを保存すると、後続の接続でパスワードを入力する必要がなくなります。mysqlsh --js <username>@<IP>:3306
クラスタを作成します。 <cluster_name> はクラスタ名に置き換えます。
<cluster_name>var cluster = dba.createCluster('<cluster_name>');セカンダリノードをクラスターに追加します。
<username>は、「ステップ 1: クラスターノードを構成する」で作成した MySQL アカウントのユーザー名に置き換え、<IP>はセカンダリノードの IP アドレスに置き換えます。すべてのセカンダリノードを追加するには、このステップを繰り返します。説明たとえば、IP アドレス
192.168.2.1とユーザー名cluster_userを持つノードを追加するには、cluster.addInstance('cluster_user@192.168.2.1:3306');コマンドを実行します。cluster.addInstance('<username>@<IP>:3306');次の出力は、セカンダリノードが追加されたことを示しています。

クラスタの状態を確認します。
cluster.status();次の出力は、クラスタが作成されたことを示しています。

ステップ 3:プロキシノードを構成する
ECS インスタンス A に接続します。詳細については、「Workbench を使用して SSH 経由で Linux インスタンスに接続する」をご参照ください。
プロキシ設定を初期化します。
<username>は、「手順 1:クラスタノードを構成する」で作成した MySQL アカウントのユーザー名に置き換え、<IP>はプライマリノードの IP アドレスに置き換えます。プロンプトが表示されたら、MySQL アカウントのパスワードを入力します。説明デフォルトでは、コマンドは初期化ファイルを
/mnt/mysqlrouterディレクトリに保存します。sudo mysqlrouter --bootstrap <username>@<IP>:3306 --directory /mnt/mysqlrouter \ --conf-bind-address 0.0.0.0 --user=mysqlroutermysqlrouter サービスファイルを編集します。
説明デフォルトでは、コマンドは
/mnt/mysqlrouterディレクトリを使用します。ディレクトリを変更した場合は、ExecStart パスと ExecStop パスを更新する必要があります。sudo tee /usr/lib/systemd/system/mysqlrouter.service <<-'EOF' [Unit] Description=MySQL Router Service After=network.target [Service] User=mysqlrouter Group=mysqlrouter Type=forking ExecStart=/mnt/mysqlrouter/start.sh ExecStop=/mnt/mysqlrouter/stop.sh Restart=on-failure StandardOutput=journal [Install] WantedBy=multi-user.target EOFmysqlrouter サービスを開始します。
#サービスファイルを更新します。 sudo systemctl daemon-reload #mysqlrouter サービスを開始します。 sudo systemctl start mysqlrouter.service #mysqlrouter が起動時に自動的に開始されるように構成します。 sudo systemctl enable mysqlrouter.service #mysqlrouter サービスの状態を確認します。 sudo systemctl status mysqlrouter.service
クラスタを検証する
プライマリノード(ECS インスタンス B)を停止して障害をシミュレートし、クラスタが自動的にノードを切り替えてサービスを提供し続けることを検証します。
ECS インスタンス A に接続します。詳細については、「Workbench を使用して SSH 経由で Linux インスタンスに接続する」をご参照ください。
MySQL クライアントを使用して、プロキシノード(ECS インスタンス A)に接続します。
<username>は、「手順 1:クラスタノードを構成する」で作成した MySQL アカウントのユーザー名に置き換えます。mysql -h127.0.0.1 -P6450 -u<username> -p次の SQL 文を実行して、クラスタの状態を確認します。結果は、3 つのノードがオンラインで、1 つのノードがプライマリノードとして機能していることを示しています。
SELECT * FROM performance_schema.replication_group_members;
SQL 文を実行して、テストデータベースとテストテーブルを追加します。
-- 1. データベースを作成します。 CREATE DATABASE test_db; -- 2. データベースを使用します。 USE test_db; -- 3. test_table という名前のテーブルを作成します。 CREATE TABLE test_table ( id INT AUTO_INCREMENT PRIMARY KEY, -- 自動インクリメント プライマリキー name VARCHAR(100) NOT NULL, -- 名前 value DECIMAL(10, 2) NOT NULL ); -- 4. test_table にエントリを追加します。 INSERT INTO test_table (name, value) VALUES ('Item A', 100.50), ('Item B', 200.75);プライマリノード(ECS インスタンス B)を停止して、故障イベントをシミュレートします。
プライマリノードが停止した後、次の SQL 文を再度実行して、クラスタの状態を確認します。 2 つのノードがオンラインで、セカンダリノードがプライマリノードになっていることがわかります。
SELECT * FROM performance_schema.replication_group_members;
次の SQL 文を実行してデータをクエリし、データ損失を確認します。
SELECT * FROM test_table;プライマリノード(ECS インスタンス B)を起動して、故障からの回復をシミュレートします。
次の SQL 文を実行して、クラスタの状態を確認します。結果は、3 つのノードがオンラインで、ECS インスタンス B が自動的にクラスタに参加していることを示しています。
SELECT * FROM performance_schema.replication_group_members;
クラスタにノードを追加する
MySQL InnoDB Cluster をスケールアップする場合、またはクラスタ内のノードに障害が発生した場合は、MySQL Shell を使用してクラスタに接続し、 addInstance コマンドを実行して新しいノードを追加します。新しいノードは自動的にデータを同期します。addInstance を追加
クラスタ内のノードの半分以上が故障すると、クラスタは使用できなくなります。可用性を確保するために、クラスタ内のノード数を奇数に構成することをお勧めします。
ノードがクラスタに参加する前に、ノードに MySQL をインストールし、ステップ 1:クラスタノードを構成する の手順 2、3、および 4 を実行して構成します。
ECS インスタンス A に接続します。詳細については、「Workbench を使用して SSH 経由で Linux インスタンスに接続する」をご参照ください。
MySQL Shell を使用して、クラスタ内の任意のノードに接続します。 <username> は、
<username>ステップ 1:クラスタノードを構成する で作成した MySQL アカウントのユーザー名に置き換え、<IP> はノードの IP アドレスに置き換えます。 MySQL アカウントのパスワードを入力し、プロンプトが表示されたらパスワードを保存するかどうかを選択します。パスワードを保存すると、後続の接続でパスワードを入力する必要がなくなります。<IP>mysqlsh --js <username>@<IP>:3306クラスタ情報を取得します。
var cluster = dba.getCluster();クラスタにノードを追加します。
<username>は、「手順 1: クラスタノードを構成する」で作成した MySQL アカウントのユーザー名に置き換え、<IP>はノードの IP アドレスに置き換えます。説明たとえば、IP アドレス
192.168.2.1とユーザー名cluster_userを使用してノードを追加するには、cluster.addInstance('cluster_user@192.168.2.1:3306');コマンドを実行します。cluster.addInstance('<username>@<IP>:3306');次の出力は、ノードが追加されたことを示しています。

クラスタのプライマリノードを指定する
MySQL InnoDB Cluster では、プライマリノードに障害が発生した場合、残りのノードから新しいプライマリノードが自動的に選出されます。 MySQL Shell を使用してクラスターに接続し、setPrimaryInstance コマンドを実行して、プライマリノードを手動で指定できます。
ECS インスタンス A に接続します。詳細については、「Workbench を使用して SSH 経由で Linux インスタンスに接続する」をご参照ください。
MySQL Shell を使用して、クラスタ内の任意のノードに接続します。
<username>は、「手順 1: クラスタノードを構成する」で作成した MySQL アカウントのユーザー名に置き換え、<IP>はノードの IP アドレスに置き換えます。 MySQL アカウントのパスワードを入力し、プロンプトが表示されたらパスワードを保存するかどうかを選択します。パスワードを保存すると、後続の接続でパスワードを入力する必要がなくなります。mysqlsh --js <username>@<IP>:3306クラスタ情報を取得します。
var cluster = dba.getCluster();クラスターのプライマリノードを指定します。
<username>は、「手順 1: クラスタノードを構成する」で作成した MySQL アカウントのユーザー名に置き換え、<IP>はノードの IP アドレスに置き換えます。説明たとえば、IP アドレス 192.168.2.1 とユーザー名 cluster_user を持つノードをプライマリノードとして指定するには、 cluster.setPrimaryInstance('cluster_user@192.168.2.1:3306'); コマンドを実行します。
cluster.setPrimaryInstance('<username>@<IP>:3306');次の出力は、ノードがプライマリノードとして構成されたことを示しています。

参考文献
MySQL InnoDB Cluster については、MySQL 公式ドキュメントをご参照ください。
デプロイと管理を簡素化するために、ApsaraDB RDS を使用することをお勧めします。詳細については、「ApsaraDB RDS for MySQL とは」をご参照ください。
CPU、メモリ、ディスク I/O、ネットワークトラフィックなどのメトリックを含め、クラスタサービスをリアルタイムで監視して、例外を迅速に検出して処理します。詳細については、「CloudMonitor とは」をご参照ください。