これは、なにをしたくて書いたもの?
以前、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は、InnoDB Clusterの一部であり、MySQLを利用するアプリケーションから見た、MySQLサーバー群へのルーティングを
提供するミドルウェアです。
MySQL :: MySQL Router 8.0
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
UNIXドメインソケットを使ってくれ、だそうです。
とまあ、前置きはこれくらいにして試してみましょう。
環境
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
--bootstrap URI, -B URI
ここで、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」になっています。
routing_strategy
試しに、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のメタデータの再設定が必要なようなので、そちらも確認してみるとしましょう。