MySQL RouterでRDSのReplicaを負荷分散してみる

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

ウィスキー、シガー、パイプをこよなく愛する大栗です。

MySQLやAuroraでRead Heavyな環境だとだとRead Replicaを多数用意すると思います。多数のRead Replicaを効率的に使用するためにはリクエストの負荷分散が必須です。MySQLの負荷分散を行うためのプロダクトはいくつかありますが、今回はMySQL Routerを試してみました。

MySQL Router

MySQL Router

プロダクトのページにトップには、以下の様な記載があります。透過的なルーティングと言うことで、MySQLに接続するつもりでMySQL Routerに接続すれば良いということです。

MySQL Routerはアプリケーションと任意のバックエンドのMySQLサーバー間の透過的なルーティングを提供する軽量のミドルウェアです。データベースへの接続を適切なバックエンドのMySQLサーバーへ効果的に ルーティングすることにより、高可用性や拡張性の提供など、様々なユースケースで使用できます。

類似のプロダクトでは、代表的なものに以下の様なものがあります。

  • MySQL専用プロダクト
  • 汎用プロトコルのプロダクト
    • HAProxy:HAPrxoy 1.6.0から動的名前解決ができるようになっていてRDSの様なエンドポイントが固定されるサービスで使いやすくなっています。
    • nginx:1.9.0以降はtcpの汎用ロードバランシングができるようになっている様です。

MySQL Routerをインストールしてみる

以下の環境に導入してみます。

  • OS:Amazon Linux 2016.03
  • EC2:t2.small
  • リージョン:東京

Download MySQL Yum RepositoryのページからリポジトリのRPMをダウンロードします。Amazon Linuxでは『Red Hat Enterprise Linux 6 / Oracle Linux 6 (Architecture Independent), RPM Package』のパッケージを選択します。2016年8月31日現在でファイル名はmysql57-community-release-el6-8.noarch.rpmとなっています。

パッケージをインストールしてMySQLのリポジトリを登録します。

$ sudo rpm -Uvh /path/to/mysql57-community-release-el6-8.noarch.rpm

MySQL Routerをインストールします。

$ sudo yum install mysql-router -y

設定ファイルは、/etc/mysqlrouter/mysqlrouter.iniにあります。

# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA

#
# MySQL Router configuration file
#
# Documentation is available at
#    http://dev.mysql.com/doc/mysql-router/en/

[DEFAULT]
logging_folder = /var/log/mysqlrouter/
plugin_folder = /usr/lib64/mysqlrouter
runtime_folder = /var/run/mysqlrouter
config_folder = /etc/mysqlrouter

[logger]
level = info

# If no plugin is configured which starts a service, keepalive
# will make sure MySQL Router will not immediately exit. It is
# safe to remove once Router is configured.
[keepalive]
interval = 60

MySQL Routerを構成する

MySQL for RDSでMasterが1台、Read Replicaが2台の環境に対して、以下のように設定してみます。MySQL Routerの受付ポートはMaster側を13306、Read Replica側を23306として設定します。

Untitled (1)

mysqlrouter.iniは以下のように構成しました。37行目以降を追加しています。Masterへ向ける接続はread-writeモードに設定して、Replicaに向ける接続はread-onlyモードに設定して負荷分散をしています。

# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA

#
# MySQL Router configuration file
#
# Documentation is available at
#    http://dev.mysql.com/doc/mysql-router/en/

[DEFAULT]
logging_folder = /var/log/mysqlrouter/
plugin_folder = /usr/lib64/mysqlrouter
runtime_folder = /var/run/mysqlrouter
config_folder = /etc/mysqlrouter

[logger]
level = info

# If no plugin is configured which starts a service, keepalive
# will make sure MySQL Router will not immediately exit. It is
# safe to remove once Router is configured.
[keepalive]
interval = 60

[routing:master]
bind_address = 0.0.0.0:13306
destinations = master.abcdefghijkl.ap-northeast-1.rds.amazonaws.com
mode = read-write

[routing:replica]
bind_address = 0.0.0.0:23306
destinations = slave1.abcdefghijkl.ap-northeast-1.rds.amazonaws.com,slave2.abcdefghijkl.ap-northeast-1.rds.amazonaws.com
mode = read-only

動作を確認してみる

MySQL Routerへ接続して動作を確認してみます。
まずはMasterへ接続してみます。

$ mysql -u awsuser -p -P 13306 -h 127.0.0.1
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 91
Server version: 5.6.27-log MySQL Community Server (GPL)

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show variables like 'hostname';
+---------------+--------------+
| Variable_name | Value        |
+---------------+--------------+
| hostname      | ip-10-7-2-19 |
+---------------+--------------+
1 row in set (0.00 sec)

mysql>

ますはMasterへ接続してみます。次にReplicaへ接続してみます。

$ mysql -u awsuser -p -P 23306 -h 127.0.0.1
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 17
Server version: 5.6.27 MySQL Community Server (GPL)

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show variables like 'hostname';
+---------------+---------------+
| Variable_name | Value         |
+---------------+---------------+
| hostname      | ip-10-7-2-140 |
+---------------+---------------+
1 row in set (0.00 sec)

mysql>

負荷分散されているか、Replica側に連続してアクセスしてホスト名を確認してみます。以下のように交互に異なるインスタンスへアクセスしていることが分かります。

$ echo "show variables like 'hostname';" | mysql -u awsuser -pmypassword -P 23306 -h 127.0.0.1
Variable_name  	Value
hostname       	ip-10-7-1-94
$ echo "show variables like 'hostname';" | mysql -u awsuser -pmypassword -P 23306 -h 127.0.0.1
Variable_name  	Value
hostname       	ip-10-7-2-140
$ echo "show variables like 'hostname';" | mysql -u awsuser -pmypassword -P 23306 -h 127.0.0.1
Variable_name  	Value
hostname       	ip-10-7-1-94
$ echo "show variables like 'hostname';" | mysql -u awsuser -pmypassword -P 23306 -h 127.0.0.1
Variable_name  	Value
hostname       	ip-10-7-2-140

さいごに

MySQL Routerを使用するとアプリに手を入れずに、手軽にReplicaの負荷分散ができるようになります。まだ、名前解決のキャッシュ状況などを検証できていないので実運用での活用方法が確認できていないので、今後検証を進めていきたいと思います。