Tungsten Replicatorを使って、非RDS→RDSのMySQLレプリケーションを行う

都元です。AWS上に構築するシステムAにおいて、非AWS上で稼働する別システムBで利用しているマスタデータを使いたい、という状況ってありえますよね。既にシステムBは非AWS環境で動いていて、そこで使っているマスタデータを、AWS上に新規構築するシステムBでも使いたい。そして、システムA上でマスタ更新が掛かったら、システムBのマスタも更新されて欲しい、というわけです。

システムA,B共にAWS上にあれば、理想的な解決方法もあるでしょう。逆に、システムBがRDSでさえなければ、MySQL標準のレプリケーション機能を使うこともできるでしょう。しかし、RDSを使う場合は、標準のレプリケーション機能を利用することはできません *1

というわけで、今回のような非RDSをmasterとするRDSへのレプリケーションでは、サードパーティ製プロダクトのお世話になる必要がありそうです。今回はTungsten Replicatorというプロダクトを使ってみます。

Tungsten Replicator

Tungsten Replicatorは、OSSのMySQL用データレプリケーションエンジンです。ドキュメントを見てみると、MySQLからOracleへの異種RDBMSレプリケーション、さらにはMySQLからMongoDBへのレプリケーションまでこなすような、挑戦的なプロジェクトですね。今回はさすがに、このような奇抜な機能にはチャレンジしませんが、そのうち触ってみると面白そうです。

Tungsten Replicator(以下、tungsten)によるMySQLのレプリケーションは、ざっくりと次のようなアーキテクチャとなっています。混乱しないように先に明らかにしておきますが、このアーキテクチャではtungstenのプロセスが2つ登場します。1つをtungsten-master、もう1つをtungsten-bridgeと呼ぶことにします *2

  1. レプリケーションマスタ側のMySQL(以下、mysql-master)に対して、バイナリログをデータディレクトリに出力するように設定を行う。
  2. tungsten-masterは、mysql-masterのバイナリログを読み出し、THL(Transaction History Log)というtungsten独自形式のログとして保持する。
  3. tungsten-bridgeは、tungsten-masterが保持するTHLを読み出し、レプリケーションスレーブ側のMySQL(以下、mysql-slave)に対してトランザクションを適用する。

といった感じです。今回の場合、mysql-masterはMySQL on EC2です。そして、そのEC2インスタンス上でtungsten-masterを稼働させます(下図左側のインスタンス)。tungsten-bridgeも同じインスタンスで稼働できれば良かったのですが、ポート番号の衝突等で設定が複雑になるため、今回はtungsten-bridgeを稼働させるためのEC2インスタンスを別に立てるような構成にしました(下図中央のEC2インスタンス)。そして、mysql-slaveはEC2ではなくRDSです(下図右側のRDSインスタンス)。図中ではMulti-AZとして書いてありますが、Single-AZでも構わないでしょう。

tungsten

話の導入部で「非AWS上で稼働する別システムB」という表現をしましたが、AWS内で話を完結させるために、MySQL on EC2として説明を進めます。

さて、この検証の為の環境ですが、VPC作ってSubnet作って、というのは相変わらず大変なので、検証用のCloudFormationテンプレートを用意しました。このテンプレートは、素の状態のEC2を2台(10.0.0.10及び10.0.0.20)、RDS(Single-AZ)を1台作り、用途に応じたSecurityGroupを設定するだけなので、MySQLやtungstenの設定は手動でやっていきましょう。

必要なパラメータは、各EC2インスタンス用のキーペア名と、RDSのマスタパスワード(default: slavepass)のみです。適切に設定してスタックを作成してください。スタックの生成に掛かる時間は、約15分です。

さて、スタックの生成が終わったら、Outputsにいくつかの出力があります。tungsten-masterへのSSH接続コマンド例(SSHToTungstenMaster)、tungsten-bridgeへのSSH接続コマンド例(SSHToTungstenBridge)、及びmysql-slaveのホスト名(MySQLSlaveHostname)です。

mysql-master及びtungsten-masterのセットアップ

まずSSHToTungstenMasterを使ってSSH接続し、mysql-master及びtungsten-masterをセットアップしていきます。まず、/etc/hostsにエントリを追記し、ip-10.0.0.10というホスト名を確実に認識させます。

$ echo "10.0.0.10   ip-10-0-0-10" | sudo tee -a /etc/hosts

次に、MySQLをインストールし、

$ sudo yum -y install mysql-server

/etc/my.cnf[mysqld]セクションに以下の設定を追加の上、

innodb-file-per-table=1
server-id=1
log-bin=mysql-bin
innodb-flush-method=O_DIRECT
max_allowed_packet=52M
innodb-thread-concurrency=0
default-storage-engine=innodb

起動し、rootのパスワードを設定します。

$ sudo /etc/init.d/mysqld start
$ mysqladmin -u root password masterpass

mysql-masterはこんなもんですね。続いて、tungsten-masterをセットアップします。

$ mkdir ~/staging
$ cd ~/staging
$ wget --no-check-certificate https://s3.amazonaws.com/files.continuent.com/builds/nightly/tungsten-2.0-snapshots/tungsten-replicator-2.0.7-177.tar.gz
$ tar zxvf tungsten-replicator-2.0.7-177.tar.gz
$ sudo mkdir /opt/continuent
$ sudo chown ec2-user /opt/continuent

$ tungsten-replicator-2.0.7-177/tools/tungsten-installer \
  --master-slave \
  --master-host=localhost \
  --datasource-user=root \
  --datasource-password=masterpass \
  --service-name=aws \
  --home-directory=/opt/continuent \
  --cluster-hosts=localhost \
  --start-and-report

以上でセットアップ完了です。以下のコマンドを打った時、state : ONLINEという出力があれば、問題なく動いています。何かおかしいな、と思ったら下記のコマンドを使って状況を確認すると良いです。

$ /opt/continuent/releases/tungsten-replicator-2.0.7-177/tungsten-replicator/bin/trepctl -host localhost status

tungsten-bridgeのセットアップ

さて、続いてtungsten-bridge側です。SSHToTungstenBridgeを使ってSSH接続し、同じように/etc/hostsを以下のように書換え、ip-10.0.0.20というホスト名を確実に認識させます。

$ echo "10.0.0.20   ip-10-0-0-20" | sudo tee -a /etc/hosts

次に、MySQLのクライアントをインストールしておきましょう。

$ sudo yum -y install mysql

続いて、tungsten-slaveをセットアップします。tungsten-installerのコマンド内には、mysql-slaveのホスト名を指定するオプション--datasource-hostがありますので、下記のままコピペせず、この部分をMySQLSlaveHostnameに書き換えるのを忘れないでください。

$ mkdir ~/staging
$ cd ~/staging
$ wget --no-check-certificate https://s3.amazonaws.com/files.continuent.com/builds/nightly/tungsten-2.0-snapshots/tungsten-replicator-2.0.7-177.tar.gz
$ tar zxvf tungsten-replicator-2.0.7-177.tar.gz
$ sudo mkdir /opt/continuent
$ sudo chown ec2-user /opt/continuent

$ tungsten-replicator-2.0.7-177/tools/tungsten-installer \
  --master-slave \
  --cluster-hosts=localhost \
  --master-host=10.0.0.10 \
  --datasource-host=********.rds.amazonaws.com \
  --datasource-user=root \
  --datasource-password=slavepass \
  --service-name=aws \
  --slave-privileged-updates=false \
  --home-directory=/opt/continuent \
  --skip-validation-check=InstallerMasterSlaveCheck \
  --skip-validation-check=MySQLPermissionsCheck \
  --start-and-report

以上でセットアップ完了です。tungsten-masterの時と同様に、以下のコマンドを打った時、state : ONLINEという出力があれば、問題なく動いています。

$ /opt/continuent/releases/tungsten-replicator-2.0.7-177/tungsten-replicator/bin/trepctl -host localhost status

検証

さて、まずはmysql-master及びmysql-slave、両者の状況を確認しておきましょう。tungsten_awsというテーブルがありますが、これはtungstenが内部的に利用するDBです。

[mysql-master]$ mysql -u root -p
Enter password: masterpass
mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
| tungsten_aws       |
+--------------------+
5 rows in set (0.00 sec)
[mysql-bridge]$ mysql -u root -h ********.rds.amazonaws.com -p
Enter password: slavepass
mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| innodb             |
| mysql              |
| performance_schema |
| tungsten_aws       |
+--------------------+
5 rows in set (0.03 sec)

ここで、mysql-masterに適当なデータを突っ込みます。

mysql> CREATE DATABASE cmsampledb;
mysql> CREATE TABLE cmsampledb.cmsampletable (id INT AUTO_INCREMENT PRIMARY KEY, value VARCHAR(128) NOT NULL);
mysql> INSERT INTO cmsampledb.cmsampletable (value) VALUES ('foo');
mysql> SELECT * FROM cmsampledb.cmsampletable;
+----+-------+
| id | value |
+----+-------+
|  1 | foo   |
+----+-------+
1 row in set (0.00 sec)

そこでmysql-slaveの状況をあらためて確認すると、データベースが増えていますね。

mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| cmsampledb         |
| innodb             |
| mysql              |
| performance_schema |
| tungsten_aws       |
+--------------------+
6 rows in set (0.03 sec)

中身も追従もしっかり行われていますね!

mysql> USE cmsampledb;
Database changed
mysql> SHOW TABLES;
+----------------------+
| Tables_in_cmsampledb |
+----------------------+
| cmsampletable        |
+----------------------+
1 row in set (0.00 sec)
mysql> SELECT * FROM cmsampletable;
+----+-------+
| id | value |
+----+-------+
|  1 | foo   |
+----+-------+
1 row in set (0.00 sec)

参考

脚注

  1. 参考: AWSのRDSは外部のMySQLとレプリケーションできない -マスターユーザの権限を見て分かったこと-
  2. これらは本エントリで勝手に付けた名前ですので、正確な用語使いにはなっていない気がしますのでご注意。