MySQL InnoDB Cluster練習


[MySQL 8\.0\.13 で MySQL InnoDB Cluster を構築する \| スマートスタイル TECH BLOG｜データベース＆クラウドの最新技術情報を配信](https://blog.s-style.co.jp/2018/11/2722/)
の写経

## 所感

- 従来のようなレプリケーション設定ではファイル変更必須だったが、コマンド実行だけで構築簡単
- nodeがダウンすると良い感じにプライマリが切り替わる
- 復帰すると良い感じにセカンダリへ
- 如何せんまだまだWebにノウハウが多いとは言えない
- routerがいればnodeがダウンしても自動的に接続先を切り替えてくれるが、router自体の冗長化はどうするのかとなるが、各アプリケーション・サーバーにrouterを入れるのが正解？

## 構成

- docker-composeでOSはAlmaLinux8。（あえて公式mysqlコンテナを使わず）
- mysqlのバージョンはmysql-server-8.0.21（現在最新）

| マシン | IP | ホスト名 |
|:-|:-|:-|
| MySQL Shell | 172.30.0.2  | shell  |
| MySQL Router | 172.30.0.3  |  router |
| MySQL Server (node1)  | 172.30.0.11  |  node1 |
| MySQL Server (node2)  | 172.30.0.12 | node2  |

## docker-composeファイル

```yml:docker-compose.yml
# vim: set ts=2 et:
version: '3.5'

services:
  shell:
    image: almalinux/almalinux:8
    hostname: shell
    privileged: true
    command: /sbin/init
    networks:
      app_net:
        ipv4_address: 172.30.0.2
  router:
    image: almalinux/almalinux:8
    hostname: router
    privileged: true
    command: /sbin/init
    networks:
      app_net:
        ipv4_address: 172.30.0.3
  node1:
    image: almalinux/almalinux:8
    hostname: node1
    privileged: true
    command: /sbin/init
    networks:
      app_net:
        ipv4_address: 172.30.0.11
  node2:
    image: almalinux/almalinux:8
    hostname: node2
    privileged: true
    command: /sbin/init
    networks:
      app_net:
        ipv4_address: 172.30.0.12

networks:
  app_net:
    name: app_net
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.30.0.0/24
```

※ポート3306を公開していないのでアクセスできないのはとりあえず気にしない

各サーバーへのログインは
`docker-compose exec node1 /bin/bash`

## 構築

```sh
// node1～2で実行
# dnf install -y https://dev.mysql.com/get/mysql80-community-release-el8-1.noarch.rpm
# dnf install -y mysql-server
# systemctl start mysqld
# mysql
mysql> create user 'root'@'172.30.0.%' identified by 'Password1!';
mysql> grant all on *.* to 'root'@'172.30.0.%' with grant option;
```

```sh
// shellで実行
# dnf install -y https://dev.mysql.com/get/mysql80-community-release-el8-1.noarch.rpm
# dnf install -y mysql-shell
// MySQL Group Replication の各インスタンスの設定
# mysqlsh
MySQL JS> dba.configureInstance('root@node1')
Do you want to perform the required configuration changes? [y/n]: y
Do you want to restart the instance after configuring it? [y/n]: y
MySQL JS> dba.configureInstance('root@node2')
Do you want to perform the required configuration changes? [y/n]: y
Do you want to restart the instance after configuring it? [y/n]: y
MySQL JS> dba.checkInstanceConfiguration('root@node1')
MySQL JS> dba.checkInstanceConfiguration('root@node2')
// MySQL Group Replication のクラスターを組む
MySQL JS> \c root@node1
MySQL JS> cluster = dba.createCluster('mycluster')
MySQL JS> cluster.addInstance('root@node2')
MySQL JS> cluster.status()

// 二回目接続時
# mysqlsh
MySQL JS> \c root@node1
MySQL JS> cluster = dba.getCluster()
MySQL JS> cluster.status()
```

```sh
// routerで実行
# dnf install -y https://dev.mysql.com/get/mysql80-community-release-el8-1.noarch.rpm
# dnf install -y mysql-router-community
# mysqlrouter --bootstrap root@node1 --user=mysqlrouter
## MySQL Classic protocol

- Read/Write Connections: localhost:6446
- Read/Only Connections:  localhost:6447

## MySQL X protocol

- Read/Write Connections: localhost:6448
- Read/Only Connections:  localhost:6449
# systemctl start mysqlrouter
```

```sh
// （mysqlコマンドが入っていればどこからでもよいので）routerに接続
# mysql -u root -p -h router -P 6446 --prompt="mysql-\p> "
mysql-6446>
```

## 確認

```sh
// mode1で実行
# mysql
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
| group_replication_applier | 607e2f00-ab3e-11eb-9608-0242ac1e000b | node1       |        3306 | ONLINE       | PRIMARY     | 8.0.21         |
| group_replication_applier | 6167af21-ab3e-11eb-853a-0242ac1e000c | node2       |        3306 | ONLINE       | SECONDARY   | 8.0.21         |
+---------------------------+--------------------------------------+-------------+-------------+--------------+-------------+----------------+
2 rows in set (0.00 sec)
```

```sh
// shellで実行
# mysqlsh
MySQL JS> \c root@node1
MySQL JS> cluster = dba.getCluster()
MySQL JS> cluster.status()
{
    "clusterName": "mycluster",
    "defaultReplicaSet": {
        "name": "default",
        "primary": "node1:3306",
        "ssl": "REQUIRED",
        "status": "OK_NO_TOLERANCE",
        "statusText": "Cluster is NOT tolerant to any failures.",
        "topology": {
            "node1:3306": {
                "address": "node1:3306",
                "memberRole": "PRIMARY",
                "mode": "R/W",
                "readReplicas": {},
                "replicationLag": null,
                "role": "HA",
                "status": "ONLINE",
                "version": "8.0.21"
            },
            "node2:3306": {
                "address": "node2:3306",
                "memberRole": "SECONDARY",
                "mode": "R/O",
                "readReplicas": {},
                "replicationLag": null,
                "role": "HA",
                "status": "ONLINE",
                "version": "8.0.21"
            }
        },
        "topologyMode": "Single-Primary"
    },
    "groupInformationSourceMember": "node1:3306"
}
MySQL JS> cluster.listRouters()
{
    "clusterName": "mycluster",
    "routers": {
        "router::system": {
            "hostname": "router",
            "lastCheckIn": null,
            "roPort": 6447,
            "roXPort": 6449,
            "rwPort": 6446,
            "rwXPort": 6448,
            "version": "8.0.24"
        }
    }
}
```


[CentOSにMySQLのインストール/アンインストール \- Qiita](https://qiita.com/ishino_mezon/items/9738ceced4eed005e754)
[MySQL 8\.0\.13 で MySQL InnoDB Cluster を構築する \| スマートスタイル TECH BLOG｜データベース＆クラウドの最新技術情報を配信](https://blog.s-style.co.jp/2018/11/2722/)
[docker\-composeで作成されるものの名前を明示的に指定する方法 \- Qiita](https://qiita.com/satodoc/items/188a387f7439e4ec394f)
[docker\-composeでコンテナの内部IPアドレスを固定化してWebサイトを作る \- sagantaf](https://sagantaf.hatenablog.com/entry/2020/02/11/002149)
[MySQL InnoDB Cluster を使って運用を手抜きしよう \- Speaker Deck](https://speakerdeck.com/masayuki14/mysql-innodb-cluster-woshi-tuteyun-yong-woshou-ba-kisiyou)
[MySQL Routerの冗長化について \- 2000秒後の私へ](https://puan.hatenadiary.jp/entry/2020/04/03/020927)
[オンラインで MySQL InnoDB Cluster の構成を変更する \| スマートスタイル TECH BLOG｜データベース＆クラウドの最新技術情報を配信](https://blog.s-style.co.jp/2019/02/3489/)