概要
Aurora MySQLクラスターでは、共有ストレージを使用することでクラスター配下のDBインスタンス間のレプリカラグをミリ秒レベルまで抑えています。
しかし、Auroraでは通常のMySQLのレプリケーション機能を使用することもでき、これを使用すると、Aurora MySQLクラスターから別のAurora MySQLクラスターへデータ同期することができます。
これは例えば、読み取りのみ必要とするバッチサーバがいるなどして、バッチサーバが読み取り負荷を掛けると、同じリーダーエンドポイントを参照しているサービス側にもレスポンスに影響してしまうおそれがある、などといった状況を回避するのに有効です。
MySQLの標準のレプリケーションを使用してデータが同期された別のAurora MySQLクラスターを作成し、バッチサーバはそちらにアクセスさせるようにすることで、影響を抑えることができます。
公式ドキュメントは、「[Aurora と MySQL との間、または Aurora と別の Aurora DB クラスターとの間のレプリケーション](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/AuroraMySQL.Replication.MySQL.html"Aurora と MySQL との間、または Aurora と別の Aurora DB クラスターとの間のレプリケーション")」になります。ここを参考にすすめていきます。
レプリケーション元を用意
適当にcliで作っていきます。
クラスターの作成
適当にcluster01
という名前で作ります。パラメータグループは事前に作成前提です。
$ aws rds create-db-cluster \
> --db-cluster-identifier cluster01 \
> --db-cluster-parameter-group-name cluster-param \
> --vpc-security-group-ids sg-xxxxxxxx \
> --db-subnet-group-name aurora-subnet-group \
> --engine aurora \
> --engine-version 5.6.10a \
> --port 3306 \
> --master-username <username> \
> --master-user-password <password>
クラスターにインスタンスを追加
適当にdb01
で作っています。
$ aws rds create-db-instance \
> --db-instance-identifier db01 \
> --db-instance-class db.r4.2xlarge \
> --engine aurora \
> --db-parameter-group-name db-param \
> --option-group-name default:aurora-5-6 \
> --no-publicly-accessible \
> --db-cluster-identifier cluster01 \
> --no-storage-encrypted \
> --copy-tags-to-snapshot
レプリケーション元でバイナリログ記録を有効にする
レプリケーション元に紐づくDBクラスターパラメータグループのbinlog_format
をMIXED
にします。
デフォルトでは
$ aws rds describe-db-cluster-parameters \
> --db-cluster-parameter-group-name cluster-param \
> | jq -r '.Parameters[] | select(.ParameterName == "binlog_format")'
{
"ApplyMethod": "pending-reboot",
"Description": "Binary logging format for replication",
"DataType": "string",
"IsModifiable": true,
"AllowedValues": "ROW,STATEMENT,MIXED,OFF",
"Source": "system",
"ParameterValue": "OFF",
"ParameterName": "binlog_format",
"ApplyType": "static"
}
で、OFF
になっていますので、MIXED
へ変更します。
$ aws rds modify-db-cluster-parameter-group \
> --db-cluster-parameter-group-name cluster-param \
> --parameters ParameterName=binlog_format,ParameterValue=MIXED,ApplyMethod=pending-reboot
{
"DBClusterParameterGroupName": "cluster-param"
}
MIXED
になりました。
$ aws rds describe-db-cluster-parameters \
> --db-cluster-parameter-group-name cluster-param \
> | jq -r '.Parameters[] | select(.ParameterName == "binlog_format")'
{
"ApplyMethod": "pending-reboot",
"Description": "Binary logging format for replication",
"DataType": "string",
"IsModifiable": true,
"AllowedValues": "ROW,STATEMENT,MIXED,OFF",
"Source": "user",
"ParameterValue": "MIXED",
"ParameterName": "binlog_format",
"ApplyType": "static"
}
しかしこのパラメータは再起動するまで適用されません(pending-reboot
)。
$ aws rds describe-db-clusters \
> --db-cluster-identifier cluster01 \
> | jq -r '.DBClusters[].DBClusterMembers'
[
{
"IsClusterWriter": true,
"DBClusterParameterGroupStatus": "pending-reboot",
"PromotionTier": 1,
"DBInstanceIdentifier": "db01"
}
]
再起動します。
$ aws rds reboot-db-instance \
> --db-instance-identifier db01
適用されました(in-sync
になっています)。
$ aws rds describe-db-clusters \
--db-cluster-identifier cluster01 \
| jq -r '.DBClusters[].DBClusterMembers'
[
{
"IsClusterWriter": true,
"DBClusterParameterGroupStatus": "in-sync",
"PromotionTier": 1,
"DBInstanceIdentifier": "db01"
}
]
レプリケーション元のバイナリログの保持期間を設定する
デフォルトでは、バイナリログの保持期間が設定されておらず、NULL
になっています。
$ mysql -u<username> -p<password> -h cluster01.cluster-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com -e'CALL mysql.rds_show_configuration\G'
*************************** 1. row ***************************
name: binlog retention hours
value: NULL
description: binlog retention hours specifies the duration in hours before binary logs are automatically deleted.
これを設定します。ドキュメントには、
Aurora MySQL DB クラスターのバイナリログファイルは最大 90 日間、保持できます。
とありますが、90日間(2160時間)を指定すると、
mysql> CALL mysql.rds_set_configuration('binlog retention hours', 2160);
ERROR 1644 (45000): For binlog retention hours the value must be between 1 and 168 inclusive or be NULL
となります。168時間(7日間)が上限のようです。
よくわからないので上限の7日にセットしておきます。。
mysql> CALL mysql.rds_set_configuration('binlog retention hours', 168);
Query OK, 0 rows affected (0.01 sec)
mysql> CALL mysql.rds_show_configuration\G
*************************** 1. row ***************************
name: binlog retention hours
value: 168
description: binlog retention hours specifies the duration in hours before binary logs are automatically deleted.
1 row in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
レプリケーション元にレプリケーション用ユーザを作成する
mysql> CREATE USER 'repl_user'@'10.0.0.0/255.255.0.0' IDENTIFIED BY '<password>';
mysql> GRANT REPLICATION CLIENT, REPLICATION SLAVE ON *.* TO 'repl_user'@'10.0.0.0/255.255.0.0' IDENTIFIED BY '<password>';
のような感じで、レプリケーション用ユーザを作成しておきます。
レプリケーション先ー>レプリケーション元へのアクセスを許可する
レプリケーション先のインスタンスは、前項で作成したレプリケーション用ユーザでレプリケーション元にアクセスしますので、セキュリティグループで通信を許可しておきます。
レプリケーション元のスナップショットを作成する
レプリケーション元のスナップショットを作成します。
$ aws rds create-db-cluster-snapshot \
> --db-cluster-snapshot-identifier cluster01-snapshot \
> --db-cluster-identifier cluster01
少し待つと出来上がります(available
)。
$ aws rds describe-db-cluster-snapshots \
> --db-cluster-snapshot-identifier cluster01-snapshot \
> --db-cluster-identifier cluster01 \
> | jq '.DBClusterSnapshots[].Status'
"available"
スナップショットからレプリケーション先となるAurora MySQLクラスターを作成
つくります。
$ aws rds restore-db-cluster-from-snapshot \
> --availability-zones ap-northeast-1a ap-northeast-1c \
> --db-cluster-identifier cluster02 \
> --snapshot-identifier arn:aws:rds:ap-northeast-1:123456789012:cluster-snapshot:cluster01-snapshot \
> --engine aurora \
> --engine-version 5.6.10a \
> --port 3306 \
> --db-subnet-group-name aurora-subnet-group \
> --vpc-security-group-ids sg-xxxxxxxx
クラスターパラメータグループがデフォルトになってしまうので修正します。
$ aws rds modify-db-cluster \
> --db-cluster-identifier 'cluster02' \
> --db-cluster-parameter-group-name 'cluster-param'
クラスターへインスタンスを追加します。
$ aws rds create-db-instance \
> --db-instance-identifier db02 \
> --db-instance-class db.r4.2xlarge \
> --engine aurora \
> --db-parameter-group-name db-param \
> --option-group-name default:aurora-5-6 \
> --no-publicly-accessible \
> --db-cluster-identifier cluster02 \
> --no-storage-encrypted \
> --copy-tags-to-snapshot
レプリケーション先インスタンスでレプリケーション設定をする
レプリケーション設定をします。まず、スナップショット作成時点の、レプリケーション元のバイナリログファイル名とpositionを調べます。
$ aws rds describe-events \
> --source-identifier db02 \
> --source-type db-instance
{
"Events": [
{
【略】
"EventCategories": [],
"SourceType": "db-instance",
"SourceArn": "arn:aws:rds:ap-northeast-1:123456789012:db:db02",
"Date": "2018-01-23T06:52:44.029Z",
"Message": "Binlog position from crash recovery is mysql-bin-changelog.000004 538",
"SourceIdentifier": "db02"
},
【略】
}
のようにすると確認できます。
マネジメントコンソールでも確認ができます。
バイナリログファイル名がmysql-bin-changelog.000004
、positionが538
でした。
レプリケーション先へ接続し、
mysql> CALL mysql.rds_set_external_master ('cluster01.xxxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com', 3306, 'repl_user', '<password>', 'mysql-bin-changelog.000004', 538, 0);
Query OK, 0 rows affected (0.10 sec)
mysql> CALL mysql.rds_start_replication;
+-------------------------+
| Message |
+-------------------------+
| Slave running normally. |
+-------------------------+
1 row in set (1.01 sec)
Query OK, 0 rows affected (1.01 sec)
で設定完了です。
間違ったときは、CALL mysql.rds_stop_replication;
でレプリケーションを停止して、改めてCALL mysql.rds_set_external_master
で設定し、再度CALL mysql.rds_start_replication;
すれば大丈夫です。
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: cluster01.cluster-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com
Master_User: repl_user
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin-changelog.000004
Read_Master_Log_Pos: 538
Relay_Log_File: relaylog.000002
Relay_Log_Pos: 293
Relay_Master_Log_File: mysql-bin-changelog.000004
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table: mysql.rds_history,mysql.rds_monitor,mysql.rds_sysinfo,mysql.rds_replication_status
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 538
Relay_Log_Space: 459
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 77834800
Master_UUID: 3ci19o8e-9ebd-335f-b281-10b8408311fd
Master_Info_File: mysql.slave_master_info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for the slave I/O thread to update it
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
1 row in set (0.00 sec)
Seconds_Behind_Master
が0になっていれば、レプリケーション元に追いついている状態です。
動作の確認として、レプリケーション元にデータベースを作成して、同期されるかを確認します。
レプリケーション元にデータベースを作成します。
$ mysql -u<username> -p<password> -h cluster01.cluster-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com -e'create database replication_dekirukana'
$ mysql -u<username> -p<password> -h cluster01.cluster-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com -e'show databases'
+------------------------+
| Database |
+------------------------+
| information_schema |
| mysql |
| performance_schema |
| replication_dekirukana |
+------------------------+
レプリケーション先でデータベース一覧を表示します。
$ mysql -u<username> -p<password> -h cluster02.cluster-xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com -e'show databases'
+------------------------+
| Database |
+------------------------+
| information_schema |
| mysql |
| performance_schema |
| replication_dekirukana |
+------------------------+
問題なく同期されました。
レプリカラグの監視について
Aurora MySQL -> Aurora MySQLへのMySQL標準レプリケーションの遅れは、CloudWatchのReplicaLag
ではなく、AuroraBinlogReplicaLag
を見る必要があります。
これが、show slave status
のSeconds_Behind_Master
を反映しています。
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Aurora.Monitoring.html
AuroraBinlogReplicaLag
ソース DB クラスターから Aurora MySQL DB クラスターまでの遅延時間。 このメトリクスでは、MySQL の SHOW SLAVE STATUS コマンドの Seconds_Behind_Master フィールドの値が報告され、異なる AWS リージョン間でレプリケートする Aurora DB クラスター間のレプリカの遅延を監視するのに役立ちます。
まとめ
ちょっとめんどくさいですが、無事レプリケーションを設定できました。
MySQLの標準のレプリケーションなので、レプリカラグはミリ秒単位とはならず、普通に遅れてしまう点だけ注意が必要ですが、ケースによっては有効に使えそうです。