これは、なにをしたくて書いたもの?
以前、MySQL Shellを使用して、InnoDB Clusterのうち、Group Replicationの部分を構成してみました。
MySQL Shellで、InnoDB ClusterのGroup Replication部分を構成してみる - CLOVER🍀
今度は、この構成にMySQL Routerを加えたいと思います。
Group Replication構成に、MySQL Routerを足すことで、InnoDB Clusterの完成です。
MySQL :: MySQL 8.0 Reference Manual :: 21.1 Introducing InnoDB Cluster
MySQL Router
MySQL Routerは、InnoDB Clusterの一部であり、MySQLを利用するアプリケーションから見た、MySQLサーバー群へのルーティングを
提供するミドルウェアです。
MySQL Routerを使うことで、InnoDB Clusterにおける障害時のプライマリデータベースが切り替わった時にルーティングしてくれたり、
複数のリードレプリカへの振り分けなどを行ってくれます。
MySQL :: MySQL Router 8.0 :: 1.1 Routing for MySQL InnoDB cluster
要するに、MySQL Group Replicationに対するロードバランサー的な役割になるわけですね。
MySQL :: MySQL Router 8.0 :: 1.4 Application Considerations
ちなみに、ネットワーク遅延を減らすため、MySQL Routerはそれを利用するアプリケーションと同一のホストにインストールすることが
推奨されているようです。
MySQL :: MySQL Router 8.0 :: 3 Deploying MySQL Router
とまあ、前置きはこれくらいにして試してみましょう。
環境
MySQL Serverを3つ、MySQL Router、それからMySQL Shellを用意します。
以下のサーバーを使うことにします。
- MySQL Server 1 … 172.17.0.2(mysql1)
- MySQL Server 2 … 172.17.0.3(mysql2)
- MySQL Server 3 … 172.17.0.4(mysql3)
- MySQL Router … 172.17.0.5
- MySQL Shell … 172.17.0.6
MySQLのバージョン。
# mysql --version mysql Ver 8.0.17 for Linux on x86_64 (MySQL Community Server - GPL)
MySQL Shellのバージョン。
$ mysqlsh --version Logger: Tried to log to an uninitialized logger. mysqlsh Ver 8.0.17 for Linux on x86_64 - for MySQL 8.0.17 (MySQL Community Server (GPL))
MySQL Routerのインストール
こちらに記載のaptリポジトリをインストールした後、
MySQL :: Download MySQL APT Repository
aptでインストール。
$ sudo apt install -y mysql-router
Group Replication(Single Master)を構成する
では、MySQL ShellでGroup Replication(Single Master)を構成してみましょう。
Group Replicationを構成するためのMySQL Serverの事前の設定や、ユーザーについては特に書きません。以前のエントリを参照してください。
MySQL Shellで、InnoDB ClusterのGroup Replication部分を構成してみる - CLOVER🍀
MySQL Shellでログイン。
$ mysqlsh
3つのノードを使って、Group Replicationを構成します。
MySQL JS > \connect root@172.17.0.2:3306 MySQL 172.17.0.2:3306 ssl JS > var cluster = dba.createCluster('test_single_master_cluster') MySQL 172.17.0.2:3306 ssl JS > cluster.addInstance('root@172.17.0.3:3306') MySQL 172.17.0.2:3306 ssl JS > cluster.addInstance('root@172.17.0.4:3306')
完成。
MySQL 172.17.0.2:3306 ssl JS > cluster.status() { "clusterName": "test_single_master_cluster", "defaultReplicaSet": { "name": "default", "primary": "172.17.0.2:3306", "ssl": "REQUIRED", "status": "OK", "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.", "topology": { "172.17.0.2:3306": { "address": "172.17.0.2:3306", "mode": "R/W", "readReplicas": {}, "role": "HA", "status": "ONLINE", "version": "8.0.17" }, "172.17.0.3:3306": { "address": "172.17.0.3:3306", "mode": "R/O", "readReplicas": {}, "role": "HA", "status": "ONLINE", "version": "8.0.17" }, "172.17.0.4:3306": { "address": "172.17.0.4:3306", "mode": "R/O", "readReplicas": {}, "role": "HA", "status": "ONLINE", "version": "8.0.17" } }, "topologyMode": "Single-Primary" }, "groupInformationSourceMember": "172.17.0.2:3306" }
マスターは、最初のノードですね。
"172.17.0.2:3306": { "address": "172.17.0.2:3306", "mode": "R/W", "readReplicas": {}, "role": "HA", "status": "ONLINE", "version": "8.0.17" },
では、MySQL RouterでMySQL Serverに接続して、MySQL Routerの設定を行います。「--bootstrap」オプションを指定して、
Group Replicationを構成しているMySQL Serverのうちのひとつに接続します。
$ sudo mysqlrouter --bootstrap root@172.17.0.2:3306 --user=mysqlrouter Please enter MySQL password for root:
MySQL :: MySQL 8.0 Reference Manual :: 21.3 Using MySQL Router with InnoDB Cluster
MySQL :: MySQL Router 8.0 :: 3.1 Bootstrapping MySQL Router
このコマンドを実行すると、MySQL Routerの設定ファイルなどが作成されるのですが、この時のユーザーを「--user」オプションで
指定します。
MySQL Routerはaptでインストールしているので、その時に作成される「mysqlrouter」ユーザーに合わせました。
こんな感じのログが出力されます。
# Bootstrapping system MySQL Router instance... - Checking for old Router accounts - No prior Router accounts found - Creating mysql account mysql_router1_rh4tbrc7rbpy@'%' for cluster management - Storing account in keyring - Adjusting permissions of generated files - Creating configuration /etc/mysqlrouter/mysqlrouter.conf # MySQL Router configured for the InnoDB cluster 'test_single_master_cluster' After this MySQL Router has been started with the generated configuration $ /etc/init.d/mysqlrouter restart or $ mysqlrouter -c /etc/mysqlrouter/mysqlrouter.conf the cluster 'test_single_master_cluster' can be reached by connecting to: ## MySQL Classic protocol - Read/Write Connections: localhost:6446 - Read/Only Connections: localhost:6447 ## MySQL X protocol - Read/Write Connections: localhost:64460 - Read/Only Connections: localhost:64470 Existing configuration backed up to '/etc/mysqlrouter/mysqlrouter.conf.bak'
生成された設定ファイルを見てみましょう。
/etc/mysqlrouter/mysqlrouter.conf
# File automatically generated during MySQL Router bootstrap [DEFAULT] name=system user=mysqlrouter keyring_path=/run/mysqlrouter/keyring master_key_path=/etc/mysqlrouter/mysqlrouter.key connect_timeout=15 read_timeout=30 dynamic_state=/var/run/mysqlrouter/state.json [logger] level = INFO [metadata_cache:test_single_master_cluster] router_id=1 user=mysql_router1_rh4tbrc7rbpy metadata_cluster=test_single_master_cluster ttl=0.5 use_gr_notifications=0 [routing:test_single_master_cluster_default_rw] bind_address=0.0.0.0 bind_port=6446 destinations=metadata-cache://test_single_master_cluster/default?role=PRIMARY routing_strategy=first-available protocol=classic [routing:test_single_master_cluster_default_ro] bind_address=0.0.0.0 bind_port=6447 destinations=metadata-cache://test_single_master_cluster/default?role=SECONDARY routing_strategy=round-robin-with-fallback protocol=classic [routing:test_single_master_cluster_default_x_rw] bind_address=0.0.0.0 bind_port=64460 destinations=metadata-cache://test_single_master_cluster/default?role=PRIMARY routing_strategy=first-available protocol=x [routing:test_single_master_cluster_default_x_ro] bind_address=0.0.0.0 bind_port=64470 destinations=metadata-cache://test_single_master_cluster/default?role=SECONDARY routing_strategy=round-robin-with-fallback protocol=x
接続先の定義がいろいろあります。
また、設定ファイルの中身を見てみると、Group Replicationを構成するMySQL Serverの情報は、以下のファイルに書かれているようです。
/var/run/mysqlrouter/state.json
{ "metadata-cache": { "group-replication-id": "88fcae5a-cb37-11e9-a5aa-0242ac110002", "cluster-metadata-servers": [ "mysql://172.17.0.2:3306", "mysql://172.17.0.3:3306", "mysql://172.17.0.4:3306" ] }, "version": "1.0.0" }
なお、「--bootstrap」オプションを指定して実行する度に、設定ファイルは再作成されます。
MySQL :: MySQL Router 8.0 :: 4.3.1.1 mysqlrouter — Command Line Options
ここで、MySQL Routerを再起動します。
$ sudo systemctl restart mysqlrouter.service
ところで、クラスタにサーバーが増減したりして構成に変更があった場合、こうやって「--bootstrap」オプションで設定ファイルを
再作成したり、設定ファイルを修正したりしてMySQL Routerを再起動する必要があるみたいです。
MySQL :: MySQL 8.0 Reference Manual :: 21.3 Using MySQL Router with InnoDB Cluster
Tip
When you change the topology of a cluster by adding another server instance after you have bootstrapped MySQL Router, you need to update bootstrap_server_addresses based on the updated metadata. Either restart MySQL Router using the --bootstrap option, or manually edit the bootstrap_server_addresses section of the mysqlrouter.conf file and restart MySQL Router.
「--bootstrap」を使って設定ファイルを作成した時のログに戻ると、プロトコルとアクセスする用途に応じて、
4種類のポートに分かれていることが表示されていました。
## MySQL Classic protocol - Read/Write Connections: localhost:6446 - Read/Only Connections: localhost:6447 ## MySQL X protocol - Read/Write Connections: localhost:64460 - Read/Only Connections: localhost:64470
今回は、MySQL Classic protocolと書かれている、今まで通りのプロトコルでアクセスしてみましょう。
Read/Write用は6446、Read Onlyは6447のようです。
接続して「@@hostname」を見てみます。
mysqlコマンドからアクセスしてみましょう。MySQL Routerの、Read/Write用の6446ポートに接続。
$ mysql -h 172.17.0.5 -P 6446 -uroot -p -e 'select @@hostname;' Enter password: +------------+ | @@hostname | +------------+ | mysql1 | +------------+
mysql1に接続されました。
何度接続しても、mysql1に接続が割り振られます。
$ mysql -h 172.17.0.5 -P 6446 -uroot -p -e 'select @@hostname;' Enter password: +------------+ | @@hostname | +------------+ | mysql1 | +------------+ $ mysql -h 172.17.0.5 -P 6446 -uroot -p -e 'select @@hostname;' Enter password: +------------+ | @@hostname | +------------+ | mysql1 | +------------+ $ mysql -h 172.17.0.5 -P 6446 -uroot -p -e 'select @@hostname;' Enter password: +------------+ | @@hostname | +------------+ | mysql1 | +------------+
では、Read Only用の6447ポートに接続してみましょう。
$ mysql -h 172.17.0.5 -P 6447 -uroot -p -e 'select @@hostname;' Enter password: +------------+ | @@hostname | +------------+ | mysql2 | +------------+ 1 row in set (0.0005 sec)
mysql2になりました。
Read Only用のポートの場合は、Read Only用のインスタンスに割り振られるようですね。
$ mysql -h 172.17.0.5 -P 6447 -uroot -p -e 'select @@hostname;' Enter password: +------------+ | @@hostname | +------------+ | mysql3 | +------------+ $ mysql -h 172.17.0.5 -P 6447 -uroot -p -e 'select @@hostname;' Enter password: +------------+ | @@hostname | +------------+ | mysql2 | +------------+ $ mysql -h 172.17.0.5 -P 6447 -uroot -p -e 'select @@hostname;' Enter password: +------------+ | @@hostname | +------------+ | mysql3 | +------------+
テーブル作成の確認。Read/Write側で作成。
$ mysql -h 172.17.0.5 -P 6446 -uroot -p -e 'create database test; use test; create table t1(id int);'
Read Only側で確認。
$ mysql -h 172.17.0.5 -P 6447 -uroot -p -e 'use test; select count(1) from t1;' Enter password: +----------+ | count(1) | +----------+ | 0 | +----------+
Single Master時の挙動は確認できた感じですね。
Group Replication(Multi Master)を構成する
最後に、Multi Master ModeのGroup Replicationに対して、MySQL Routerからアクセスしてみましょう。
1度環境を破棄して、Group Replicationから再構成しなおします。
マルチマスターなGroup Replicationの作成。
MySQL 172.17.0.2:3306 ssl JS > var cluster = dba.createCluster('test_multi_master_cluster', { multiPrimary: true }) MySQL 172.17.0.2:3306 ssl JS > cluster.addInstance('root@172.17.0.3:3306') MySQL 172.17.0.2:3306 ssl JS > cluster.addInstance('root@172.17.0.4:3306')
確認。
MySQL 172.17.0.2:3306 ssl JS > cluster.status() { "clusterName": "test_multi_master_cluster", "defaultReplicaSet": { "name": "default", "ssl": "REQUIRED", "status": "OK", "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.", "topology": { "172.17.0.2:3306": { "address": "172.17.0.2:3306", "mode": "R/W", "readReplicas": {}, "role": "HA", "status": "ONLINE", "version": "8.0.17" }, "172.17.0.3:3306": { "address": "172.17.0.3:3306", "mode": "R/W", "readReplicas": {}, "role": "HA", "status": "ONLINE", "version": "8.0.17" }, "172.17.0.4:3306": { "address": "172.17.0.4:3306", "mode": "R/W", "readReplicas": {}, "role": "HA", "status": "ONLINE", "version": "8.0.17" } }, "topologyMode": "Multi-Primary" }, "groupInformationSourceMember": "172.17.0.2:3306" }
「Multi-Primary」です。
では、MySQL Routerの設定。
$ sudo mysqlrouter --bootstrap root@172.17.0.2:3306 --user=mysqlrouter
MySQL Routerを再起動。
$ sudo systemctl restart mysqlrouter.service
MySQL Routerに対して、接続確認をしてみます。
まずは、Read/Writeなポートの方から。
$ mysql -h 172.17.0.5 -P 6446 -uroot -p -e 'select @@hostname;' Enter password: +------------+ | @@hostname | +------------+ | mysql1 | +------------+
mysql1です。
で、何度か試してみても…。
$ mysql -h 172.17.0.5 -P 6446 -uroot -p -e 'select @@hostname;' Enter password: +------------+ | @@hostname | +------------+ | mysql1 | +------------+ $ mysql -h 172.17.0.5 -P 6446 -uroot -p -e 'select @@hostname;' Enter password: +------------+ | @@hostname | +------------+ | mysql1 | +------------+
mysql1です。あれ、他のサーバーに行きませんね?
Read Onlyの方は、別のサーバーに割り振ってくれます。
$ mysql -h 172.17.0.5 -P 6447 -uroot -p -e 'select @@hostname;' Enter password: +------------+ | @@hostname | +------------+ | mysql1 | +------------+ $ mysql -h 172.17.0.5 -P 6447 -uroot -p -e 'select @@hostname;' Enter password: +------------+ | @@hostname | +------------+ | mysql2 | +------------+ $ mysql -h 172.17.0.5 -P 6447 -uroot -p -e 'select @@hostname;' Enter password: +------------+ | @@hostname | +------------+ | mysql3 | +------------+
ここで、以下のドキュメントを読みつつ
MySQL :: MySQL 8.0 Reference Manual :: 21.3 Using MySQL Router with InnoDB Cluster
The way incoming connections are redirected depends on the type of cluster being used. When using a single-primary cluster, by default MySQL Router publishes a X Protocol and a classic protocol port, which clients connect to for read-write sessions and which are redirected to the cluster's single primary. With a multi-primary cluster read-write sessions are redirected to one of the primary instances in a round-robin fashion. For example, this means that the first connection to port 6446 would be redirected to the ic-1 instance, the second connection to port 6446 would be redirected to the ic-2 instance, and so on. For incoming read-only connections MySQL Router redirects connections to one of the secondary instances, also in a round-robin fashion. To modify this behavior see the routing_strategy option.
MySQL Routerの設定ファイルを確認してみます。
[routing:test_multi_master_cluster_default_rw] bind_address=0.0.0.0 bind_port=6446 destinations=metadata-cache://test_multi_master_cluster/default?role=PRIMARY routing_strategy=first-available protocol=classic [routing:test_multi_master_cluster_default_ro] bind_address=0.0.0.0 bind_port=6447 destinations=metadata-cache://test_multi_master_cluster/default?role=SECONDARY routing_strategy=round-robin-with-fallback protocol=classic
Read/Writeの方の「routing_strategy」が、「first-available」になっています。
試しに、Read/Writeの方の「routing_strategy」を「round-robin」にしてみましょう。
[routing:test_multi_master_cluster_default_rw] bind_address=0.0.0.0 bind_port=6446 destinations=metadata-cache://test_multi_master_cluster/default?role=PRIMARY routing_strategy=round-robin protocol=classic
MySQL Routerを再起動。
$ sudo systemctl restart mysqlrouter.service
これで、Read/Writeの方でもラウンドロビンの接続になりました。
$ mysql -h 172.17.0.5 -P 6446 -uroot -p -e 'select @@hostname;' Enter password: +------------+ | @@hostname | +------------+ | mysql1 | +------------+ $ mysql -h 172.17.0.5 -P 6446 -uroot -p -e 'select @@hostname;' Enter password: +------------+ | @@hostname | +------------+ | mysql2 | +------------+ $ mysql -h 172.17.0.5 -P 6446 -uroot -p -e 'select @@hostname;' Enter password: +------------+ | @@hostname | +------------+ | mysql3 | +------------+
なお、シングルマスターの時に「routing_strategy」を「round-robin」にしても、プライマリであるmysql1にしか振り分けられません。
そりゃあそうですね。
レプリケーションの確認は、割愛(Read/Writeのどのサーバーで更新しても、別のサーバーに反映されます)。
ちなみに、マルチマスターの場合はRead Only接続でも更新操作ができてしまうので、注意を…。
とりあえず、マルチマスターの場合でも設定できましたが。が、ちゃんと、設定内容を理解した方がよさそうですね…。
まとめ
MySQL Routerを使って、シングルマスター、マルチマスターの場合なGroup Replication構成のMySQLに接続してみました。
Group Replicationまで組めていれば、MySQL Routerを利用すること自体はそんなに苦労はしませんでした。
今度は、ノードを増減させた場合にMySQL Routerのメタデータの再設定が必要なようなので、そちらも確認してみるとしましょう。