こんにちは。入社してから早3ヶ月が立ちましたテクニカルサポート課の森本です。
そろそろ技術ブログ書きたいな〜と思っていたところ、ちょうどRDS MySQLでマルチソースレプリケーションがサポート開始されましたので試してみました。
Amazon RDS for MySQL now supports multi-source replication
マルチソースレプリケーションとは
複数台のDBインスタンスをソース、単一のDBインスタンスをターゲットとし、レプリケーションを行います。
マルチソースレプリケーションのユースケース
以下のようなユースケースで使用されることが有用とされています。
- 個別の DB インスタンス上の複数のシャードを単一のシャードにマージまたは結合する必要があるアプリケーション
- 複数のソースより統合されたデータからレポートを生成する必要があるアプリケーション
- 複数の 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のマルチソースレプリケーションを試してみました。
バイナリログを用いたシングルマスターレプリケーションとストアドプロシージャのパラメータが微妙に違うのみであったため、思ったよりも簡単にセットアップできました。
この記事がどなたかの参考になれば幸いです。
参考ドキュメント
Amazon RDS for MySQL now supports multi-source replication
Configuring multi-source replication channels on RDS for MySQL DB instances
Managing multi-source replication - Amazon Relational Database Service