RDS MySQLのマルチソースレプリケーションを試してみた

記事タイトルとURLをコピーする

こんにちは。入社してから早3ヶ月が立ちましたテクニカルサポート課の森本です。

そろそろ技術ブログ書きたいな〜と思っていたところ、ちょうどRDS MySQLでマルチソースレプリケーションがサポート開始されましたので試してみました。

Amazon RDS for MySQL now supports multi-source replication

aws.amazon.com

マルチソースレプリケーションとは

複数台のDBインスタンスをソース、単一のDBインスタンスをターゲットとし、レプリケーションを行います。

マルチソースレプリケーションのユースケース

以下のようなユースケースで使用されることが有用とされています。

  1. 個別の DB インスタンス上の複数のシャードを単一のシャードにマージまたは結合する必要があるアプリケーション
  2. 複数のソースより統合されたデータからレポートを生成する必要があるアプリケーション
  3. 複数の RDS for MySQL DB インスタンスに分散されているデータの長期統合バックアップを作成する要件がある場合

実際の手順

事前準備

以下のリソースを作成します。レプリケーションにはバイナリログを使用するため、ソースDBインスタンスで自動バックアップを有効化します。 また、クライアントからだけでなく、ターゲットDBインスタンスからソースDBインスタンスへ3306番ポートで通信できるようセキュリティグループを設定しておきます。
*DB インスタンスはRDS MySQL 8.0.35を使用

  • ソース用のDBインスタンス2台 (source1, source2)

  • ターゲット用のDBインスタンス1台 (target)

  • クライアント用のEC2インスタンス1台

以下、こちらのドキュメントを参考に進めていきます。

Replication between Aurora and MySQL or between Aurora and another Aurora DB cluster (binary log replication) - Amazon Aurora docs.aws.amazon.com

Configuring multi-source replication channels on RDS for MySQL DB instances docs.aws.amazon.com

1. バイナリログを有効化

ソースDBインスタンスに関連づけられているパラメータグループにてバイナリログを有効化します。 こちらのパラメータは動的パラメータですが、OFFからOFF以外の値に変更した場合は有効化のためにDBインスタンスの再起動が必要です。 値がOFF以外の場合は有効化されています。 特に理由がなければMIXEDで良いと思います。

$ aws rds describe-db-parameters --db-parameter-group-name mysql8;
--中略--
{
    "ParameterName": "binlog_format",
    "ParameterValue": "MIXED",
    "Description": "Row-based, Statement-based or Mixed replication",
    "Source": "user",
    "ApplyType": "dynamic",
    "DataType": "string",
    "AllowedValues": "ROW,STATEMENT,MIXED",
    "IsModifiable": true,
    "ApplyMethod": "immediate"
}
--中略--

2. バイナリログ保持期間を変更

ソースDBインスタンスに接続し、以下のストアドプロシージャを実行します。今回は144時間(6日間)に設定しました。

source1/source2

mysql> CALL mysql.rds_set_configuration('binlog retention hours', 144);
Query OK, 0 rows affected (0.06 sec)

3. レプリケーション用のユーザ作成

ソースDBインスタンスに接続し、レプリケーション用のユーザを作成します。またレプリケーション用の権限を付与します。ソースDBインスタンス毎にユーザを変えるか、同じユーザ名を使うかは自由です。

source1/source2

mysql> CREATE USER 'repl_user'@'%' IDENTIFIED BY '******';
Query OK, 0 rows affected (0.01 sec)

mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'%';
Query OK, 0 rows affected (0.03 sec)

4. バイナリログのログファイル名とポジションを確認

ソースDBインスタンスに接続し、バイナリログのログファイル名とポジションを確認します。

source1

mysql> show master status;
+----------------------------+----------+--------------+------------------+-------------------+
| File                       | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+----------------------------+----------+--------------+------------------+-------------------+
| mysql-bin-changelog.000020 |      157 |              |                  |                   |
+----------------------------+----------+--------------+------------------+-------------------+
1 row in set (0.01 sec)

source2

mysql> show master status;
+----------------------------+----------+--------------+------------------+-------------------+
| File                       | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+----------------------------+----------+--------------+------------------+-------------------+
| mysql-bin-changelog.000024 |      157 |              |                  |                   |
+----------------------------+----------+--------------+------------------+-------------------+
1 row in set (0.01 sec)

5. 既存のデータの移行

今回はマルチソースレプリケーションの動作確認のため、既存データの移行は割愛します。

6. マルチソースレプリケーションのセットアップ

ターゲットDBインスタンスでマルチソースレプリケーションをセットアップします。4. で確認したバイナリログのログファイルとポジションを用いて、以下のストアドプロシージャを実行します。

source1用

mysql> CALL mysql.rds_set_external_source_for_channel('source1.*******.ap-northeast-1.rds.amazonaws.com', 3306, 'repl_user', '******', 'mysql-bin-changelog.000020', 157, 0, 'source1');
Query OK, 0 rows affected (0.06 sec)

source2用

mysql> CALL mysql.rds_set_external_source_for_channel('source2.*******.ap-northeast-1.rds.amazonaws.com', 3306, 'repl_user', '******', 'mysql-bin-changelog.000024', 157, 0, 'source2');
Query OK, 0 rows affected (0.06 sec)

7. マルチソースレプリケーションをスタート

ターゲットDBインスタンスでマルチソースレプリケーションをスタートします。以下のストアドプロシージャを使用し、ソース毎にスタートします。

source1用

mysql>  CALL mysql.rds_start_replication_for_channel('source1');
+------------------------------------------------------------------------------------+
| Message                                                                            |
+------------------------------------------------------------------------------------+
| Replication started for channel 'source1' and replication is now running normally. |
+------------------------------------------------------------------------------------+
1 row in set (3.02 sec)

source2用

mysql>  CALL mysql.rds_start_replication_for_channel('source2');
+------------------------------------------------------------------------------------+
| Message                                                                            |
+------------------------------------------------------------------------------------+
| Replication started for channel 'source2' and replication is now running normally. |
+------------------------------------------------------------------------------------+
1 row in set (3.02 sec)

8. 動作確認

ソースDBインスタンスでデータベースの作成やテーブルの作成、テーブルへのデータの挿入などを行い、ターゲットDBインスタンスで変更が反映されているか確認しました。

source1側

mysql> create database source1;
Query OK, 1 row affected (0.01 sec)


mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| source1            |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

mysql> use source1
Database changed

mysql> create table source1test (id int, note varchar(256));
Query OK, 0 rows affected (0.07 sec)

mysql> insert into source1test values (1,'This record is from source1');
Query OK, 1 row affected (0.01 sec)

source2側

mysql> create database source2;
Query OK, 1 row affected (0.01 sec)


mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| source2            |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

mysql> use source2
Database changed

mysql> create table source2test (id int, note varchar(256));
Query OK, 0 rows affected (0.07 sec)

mysql> insert into source2test values (1,'This record is from source2');
Query OK, 1 row affected (0.01 sec)

target側で確認

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| source1            |
| source2            |
| sys                |
+--------------------+
6 rows in set (0.00 sec)

mysql> select * from source1.source1test;
+------+-----------------------------+
| id   | note                        |
+------+-----------------------------+
|    1 | This record is from source1 |
+------+-----------------------------+
1 row in set (0.00 sec)

mysql> select * from source2.source2test;
+------+-----------------------------+
| id   | note                        |
+------+-----------------------------+
|    1 | This record is from source2 |
+------+-----------------------------+
1 row in set (0.00 sec)

ソース側での変更が、ターゲット側にマージされていることを確認できました。

まとめ

RDS MySQLのマルチソースレプリケーションを試してみました。

バイナリログを用いたシングルマスターレプリケーションとストアドプロシージャのパラメータが微妙に違うのみであったため、思ったよりも簡単にセットアップできました。

この記事がどなたかの参考になれば幸いです。

参考ドキュメント

Replication between Aurora and MySQL or between Aurora and another Aurora DB cluster (binary log replication) - Amazon Aurora

docs.aws.amazon.com

Amazon RDS for MySQL now supports multi-source replication

aws.amazon.com

Configuring multi-source replication channels on RDS for MySQL DB instances

docs.aws.amazon.com

Managing multi-source replication - Amazon Relational Database Service

docs.aws.amazon.com

森本 晃大(執筆記事の一覧)

テクニカルサポート課

2023年10月入社。絶賛仕事と子育てに奔走中です。