• 第102讲:MySQL多实例与Mycat分布式读写分离的架构实践


    1.Mycat读写分离分布式架构规划

    基于Mycat的读写分离主从复制高可用架构图如下:

    由于服务器数量有限,高可用集群由2台服务器实现,如果服务器数量很充足,那么准备8台服务器,部署8个数据库实例配置成4套MySQL主从复制集群,然后再将4套主从复制集群配置成双主双从集群,最终呈现出2套双主双从的复制集群。

    双主双从集群可以通过Mycat实现高可用功能,将双主双从配置到Mycat的数据主机里,双主双从两套主从配置成两组读写分离,两个从库同时处理读操作,两个主库,其中一个主库承担所有的写操作,另一个主库处于备用状态,当主库挂了,备用的从库接替其工作,实现高可用。

    基于Mycat打造读写分离主从复制高可用的分布式架构,通过一套双主双从即可实现,本次搭建两套双主双从是为了后期通过Mycat分库分表提供准备。

    image-20220713150137942

    (如果想在分布式架构中引入MHA,可以准备12台服务器或者是12个实例,3个为1组配置成MHA高可用集群,然后由Mycat统一管理。)

    由于服务器数量有限,我们使用2台服务器搭建基于Mycat的MySQL分布式架构。

    IP端口号角色搭建的服务
    192.168.20.113306MasterMySQL
    192.168.20.113307MasterMySQL
    192.168.20.113308SlaveMySQL
    192.168.20.113309SlaveMySQL
    192.168.20.123306MasterMySQL
    192.168.20.123307MasterMySQL
    192.168.20.123308SlaveMySQL
    192.168.20.123309SlaveMySQL

    2.在两台服务器中搭建八个MySQL实例

    2.1.安装MySQL软件

    两台服务器都操作,先将MySQL软件安装在服务器上。

    tar xf mysql-5.7.36-linux-glibc2.12-x86_64.tar.gz -C /usr/local/
    mv /usr/local/mysql-5.7.36-linux-glibc2.12-x86_64 /usr/local/mysql
    
    • 1
    • 2

    2.2.创建每个MySQL实例的数据目录并初始化

    由于两台服务器中的MySQL端口都一样,路径也保持一样,相同的命令在两台服务器中都执行。

    1.创建每个实例的数据目录
    mkdir /data/mysql{3306,3307,3308,3309}
    
    2.初始化每个实例
    mysqld --initialize-insecure  --user=mysql --datadir=/data/mysql3306 --basedir=/usr/local/mysql
    mysqld --initialize-insecure  --user=mysql --datadir=/data/mysql3307 --basedir=/usr/local/mysql
    mysqld --initialize-insecure  --user=mysql --datadir=/data/mysql3308 --basedir=/usr/local/mysql
    mysqld --initialize-insecure  --user=mysql --datadir=/data/mysql3309 --basedir=/usr/local/mysql
    
    3.授权
    chown -R mysql.mysql /data/mysql330*
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    2.3.准备每个实例的配置文件

    1)3306实例

    [root@mysql-1 ~]# vim /etc/my3306.cnf
    [mysqld]
    basedir=/usr/local/mysql
    datadir=/data/mysql3306
    socket=/data/mysql3306/mysql.sock
    port=3306
    log-error=/data/mysql3306/mysql.log
    log_bin=/data/mysql3306/mysql-bin
    binlog_format=row
    skip-name-resolve
    server-id=6
    gtid-mode=on
    enforce-gtid-consistency=true
    log-slave-updates=1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2)3307实例

    # vim /etc/my3307.cnf 
    [mysqld]
    basedir=/usr/local/mysql
    datadir=/data/mysql3307
    socket=/data/mysql3307/mysql.sock
    port=3307
    log-error=/data/mysql3307/mysql.log
    log_bin=/data/mysql3307/mysql-bin
    binlog_format=row
    skip-name-resolve
    server-id=7
    gtid-mode=on
    enforce-gtid-consistency=true
    log-slave-updates=1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    3)3308实例

    # vim /etc/my3308.cnf 
    [mysqld]
    basedir=/usr/local/mysql
    datadir=/data/mysql3308
    socket=/data/mysql3308/mysql.sock
    port=3308
    log-error=/data/mysql3308/mysql.log
    log_bin=/data/mysql3308/mysql-bin
    binlog_format=row
    skip-name-resolve
    server-id=8
    gtid-mode=on
    enforce-gtid-consistency=true
    log-slave-updates=1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    4)3309实例

    # vim /etc/my3309.cnf 
    [mysqld]
    basedir=/usr/local/mysql
    datadir=/data/mysql3309
    socket=/data/mysql3309/mysql.sock
    port=3309
    log-error=/data/mysql3309/mysql.log
    log_bin=/data/mysql3309/mysql-bin
    binlog_format=row
    skip-name-resolve
    server-id=9
    gtid-mode=on
    enforce-gtid-consistency=true
    log-slave-updates=1
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    注意第二个服务器配置的时候要修改server-id,一个集群内的server-id是不允许冲突的。

    image-20220711212337986

    2.4.准备每个实例的启动脚本

    1)3306实例

    # vim /etc/systemd/system/mysqld3306.service
    [Unit]
    Description=MySQL Server
    Documentation=man:mysqld(8)
    Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
    After=network.target
    After=syslog.target
    [Install]
    WantedBy=multi-user.target
    [Service]
    User=mysql
    Group=mysql
    ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my3306.cnf
    LimitNOFILE = 5000
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2)3307实例

    # vim /etc/systemd/system/mysqld3307.service
    [Unit]
    Description=MySQL Server
    Documentation=man:mysqld(8)
    Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
    After=network.target
    After=syslog.target
    [Install]
    WantedBy=multi-user.target
    [Service]
    User=mysql
    Group=mysql
    ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my3307.cnf
    LimitNOFILE = 5000
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    3)3308实例

    # cat /etc/systemd/system/mysqld3308.service 
    [Unit]
    Description=MySQL Server
    Documentation=man:mysqld(8)
    Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
    After=network.target
    After=syslog.target
    [Install]
    WantedBy=multi-user.target
    [Service]
    User=mysql
    Group=mysql
    ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my3308.cnf
    LimitNOFILE = 5000
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    4)3309实例

    # vim /etc/systemd/system/mysqld3309.service 
    [Unit]
    Description=MySQL Server
    Documentation=man:mysqld(8)
    Documentation=http://dev.mysql.com/doc/refman/en/using-systemd.html
    After=network.target
    After=syslog.target
    [Install]
    WantedBy=multi-user.target
    [Service]
    User=mysql
    Group=mysql
    ExecStart=/usr/local/mysql/bin/mysqld --defaults-file=/etc/my3309.cnf
    LimitNOFILE = 5000
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    2.6启动每台机器的MySQL多实例

    systemctl start mysqld3306 mysqld3307 mysqld3308 mysqld3309
    systemctl enable mysqld3306 mysqld3307 mysqld3308 mysqld3309
    systemctl status mysqld3306 mysqld3307 mysqld3308 mysqld3309
    
    • 1
    • 2
    • 3

    2.7.为每个MySQL实例设置密码

    mysqladmin -uroot -P3306 password '123456' -S /data/mysql3306/mysql.sock 
    mysqladmin -uroot -P3307 password '123456' -S /data/mysql3307/mysql.sock 
    mysqladmin -uroot -P3308 password '123456' -S /data/mysql3308/mysql.sock
    mysqladmin -uroot -P3309 password '123456' -S /data/mysql3309/mysql.sock
    
    • 1
    • 2
    • 3
    • 4

    2.8.查看每个MySQL实例的server-id

    #第一台服务器上的四个实例
    [root@mysql-1 ~]# mysql -uroot -P3306 -p123456 -S /data/mysql3306/mysql.sock -e "select @@server_id;"
    +-------------+
    | @@server_id |
    +-------------+
    |           6 |
    +-------------+
    [root@mysql-1 ~]# mysql -uroot -P3307 -p123456 -S /data/mysql3307/mysql.sock -e "select @@server_id;"
    +-------------+
    | @@server_id |
    +-------------+
    |           7 |
    +-------------+
    [root@mysql-1 ~]# mysql -uroot -P3308 -p123456 -S /data/mysql3308/mysql.sock -e "select @@server_id;"
    +-------------+
    | @@server_id |
    +-------------+
    |           8 |
    +-------------+
    [root@mysql-1 ~]# mysql -uroot -P3309 -p123456 -S /data/mysql3309/mysql.sock -e "select @@server_id;"
    +-------------+
    | @@server_id |
    +-------------+
    |           9 |
    +-------------+
    
    #第二台服务器上的四个实例
    [root@mysql-2 ~]# mysql -uroot -P3306 -p123456 -S /data/mysql3306/mysql.sock -e "select @@server_id"
    +-------------+
    | @@server_id |
    +-------------+
    |          16 |
    +-------------+
    [root@mysql-2 ~]# mysql -uroot -P3306 -p123456 -S /data/mysql3306/mysql.sock -e "select @@server_id;"
    +-------------+
    | @@server_id |
    +-------------+
    |          16 |
    +-------------+
    [root@mysql-2 ~]# mysql -uroot -P3307 -p123456 -S /data/mysql3307/mysql.sock -e "select @@server_id;"
    +-------------+
    | @@server_id |
    +-------------+
    |          17 |
    +-------------+
    [root@mysql-2 ~]# mysql -uroot -P3308 -p123456 -S /data/mysql3308/mysql.sock -e "select @@server_id;"
    +-------------+
    | @@server_id |
    +-------------+
    |          18 |
    +-------------+
    [root@mysql-2 ~]# mysql -uroot -P3309 -p123456 -S /data/mysql3309/mysql.sock -e "select @@server_id;"
    +-------------+
    | @@server_id |
    +-------------+
    |          19 |
    +-------------+
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    3.将八个MySQL实例配置成主从复制集群

    3.1.复制规划

    mysql-1服务器上的实例:

    1)3306端口为主库,3308端口为3306端口的从库。192.168.20.11:3306<-----192.168.20.11:3308

    2)3307端口为主库,3309端口为3307端口的从库。192.168.20.11:3307<-----192.168.20.11:3309

    mysql-2服务器上的实例:

    1)3306端口为主库,3308端口为3306端口的从库。192.168.20.12:3306<-----192.168.20.12:3308

    2)3307端口为主库,3309端口为3307端口的从库。192.168.20.12:3307<-----192.168.20.12:3309

    双主复制:

    1)mysql-1的3306端口与mysql-2的3306端口互相复制。

    2)mysql-1的3307端口与mysql-2的3307端口互相复制。

    如下图所示,共6对主从集群。

    image-20220711164340772

    3.2.配置mysql-1服务器中的主从复制集群

    1)3306端口为主库,3308端口为3306端口的从库。192.168.20.11:3306<-----192.168.20.11:3308

    1.192.168.20.11:3306主库上创建复制用户
    [root@mysql-1 ~]# mysql -uroot -P3306 -p123456 -S /data/mysql3306/mysql.sock -e "grant replication slave on *.* to repl@'192.168.20.%' identified by '123456';"
    [root@mysql-11 ~]# mysql -uroot -P3306 -p123456 -S /data/mysql3306/mysql.sock -e "grant all  on *.* to root@'192.168.20.%' identified by '123456'  with grant option;"
    
    2.配置192.168.20.11:3308192.168.20.11:3306的从库
    [root@mysql-1 ~]# mysql -uroot -P3308 -p123456 -S /data/mysql3308/mysql.sock -e "CHANGE MASTER TO MASTER_HOST='192.168.20.11', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123456';"
    [root@mysql-1 ~]# mysql -uroot -P3308 -p123456 -S /data/mysql3308/mysql.sock -e "start slave;"
    [root@mysql-1 ~]# mysql -uroot -P3308 -p123456 -S /data/mysql3308/mysql.sock -e "show slave status\G"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    image-20220711213948254

    2)3307端口为主库,3309端口为3307端口的从库。192.168.20.11:3307<-----192.168.20.11:3309

    1.192.168.20.11:3307主库上创建复制用户
    [root@mysql-1 ~]# mysql -uroot -P3307 -p123456 -S /data/mysql3307/mysql.sock -e "grant replication slave on *.* to repl@'192.168.20.%' identified by '123456';"
    [root@mysql-1 ~]# mysql -uroot -P3307 -p123456 -S /data/mysql3307/mysql.sock -e "grant all  on *.* to root@'192.168.20.%' identified by '123456'  with grant option;"
    
    2.配置192.168.20.11:3309192.168.20.11:3307的从库
    [root@mysql-1 ~]# mysql -uroot -P3309 -p123456 -S /data/mysql3309/mysql.sock -e "CHANGE MASTER TO MASTER_HOST='192.168.20.11', MASTER_PORT=3307, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123456';"
    [root@mysql-1 ~]# mysql -uroot -P3309 -p123456 -S /data/mysql3309/mysql.sock -e "start slave;"
    [root@mysql-1 ~]# mysql -uroot -P3309 -p123456 -S /data/mysql3309/mysql.sock -e "show slave status\G"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    image-20220711214334986

    3.3.配置mysql-2服务器中的主从复制集群

    1)3306端口为主库,3308端口为3306端口的从库。192.168.20.12:3306<-----192.168.20.12:3308

    1.192.168.20.12:3306主库上创建复制用户
    [root@mysql-2 ~]# mysql -uroot -P3306 -p123456 -S /data/mysql3306/mysql.sock -e "grant replication slave on *.* to repl@'192.168.20.%' identified by '123456';"
    [root@mysql-2 ~]# mysql -uroot -P3306 -p123456 -S /data/mysql3306/mysql.sock -e "grant all  on *.* to root@'192.168.20.%' identified by '123456'  with grant option;"
    
    2.配置192.168.20.12:3308192.168.20.12:3306的从库
    [root@mysql-2 ~]# mysql -uroot -P3308 -p123456 -S /data/mysql3308/mysql.sock -e "CHANGE MASTER TO MASTER_HOST='192.168.20.12', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123456';"
    [root@mysql-2 ~]# mysql -uroot -P3308 -p123456 -S /data/mysql3308/mysql.sock -e "start slave;"
    [root@mysql-2 ~]# mysql -uroot -P3308 -p123456 -S /data/mysql3308/mysql.sock -e "show slave status\G"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    image-20220711214702456

    2)3307端口为主库,3309端口为3307端口的从库。192.168.20.12:3307<-----192.168.20.12:3309

    1.192.168.20.12:3307主库上创建复制用户
    [root@mysql-2 ~]# mysql -uroot -P3307 -p123456 -S /data/mysql3307/mysql.sock -e "grant replication slave on *.* to repl@'192.168.20.%' identified by '123456';"
    [root@mysql-2 ~]# mysql -uroot -P3307 -p123456 -S /data/mysql3307/mysql.sock -e "grant all  on *.* to root@'192.168.20.%' identified by '123456'  with grant option;"
    
    2.配置192.168.20.12:3309192.168.20.12:3307的从库
    [root@mysql-2 ~]# mysql -uroot -P3309 -p123456 -S /data/mysql3309/mysql.sock -e "CHANGE MASTER TO MASTER_HOST='192.168.20.12', MASTER_PORT=3307, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123456';"
    [root@mysql-2 ~]# mysql -uroot -P3309 -p123456 -S /data/mysql3309/mysql.sock -e "start slave;"
    [root@mysql-2 ~]# mysql -uroot -P3309 -p123456 -S /data/mysql3309/mysql.sock -e "show slave status\G"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    image-20220711214814886

    3.4.双主复制

    1)mysql-1的3306端口与mysql-2的3306端口互相复制。192.168.20.11:3306<----->192.168.20.12:3306

    1.mysql-13306成为mysql-23306的从库
    [root@mysql-1 ~]# mysql -uroot -P3306 -p123456 -S /data/mysql3306/mysql.sock -e "CHANGE MASTER TO MASTER_HOST='192.168.20.12', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123456';"
    [root@mysql-1 ~]# mysql -uroot -P3306 -p123456 -S /data/mysql3306/mysql.sock -e "start slave;"
    [root@mysql-1 ~]# mysql -uroot -P3306 -p123456 -S /data/mysql3306/mysql.sock -e "show slave status\G"
    
    
    2.mysql-23306成为mysql-13306的从库
    [root@mysql-2 ~]# mysql -uroot -P3306 -p123456 -S /data/mysql3306/mysql.sock -e "CHANGE MASTER TO MASTER_HOST='192.168.20.11', MASTER_PORT=3306, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123456';"
    [root@mysql-2 ~]# mysql -uroot -P3306 -p123456 -S /data/mysql3306/mysql.sock -e "start slave;"
    [root@mysql-2 ~]# mysql -uroot -P3306 -p123456 -S /data/mysql3306/mysql.sock -e "show slave status\G"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    mysql-1的3306成为mysql-2的3306的从库。

    image-20220711215245229

    mysql-2的3306成为mysql-1的3306的从库。

    image-20220711215209564

    即使主库又是从库的数据库实例,线程中包含主库线程又包含从库线程。

    image-20220711215516430

    2)mysql-1的3307端口与mysql-2的3307端口互相复制。192.168.20.11:3307<----->192.168.20.12:3307

    1.mysql-13307成为mysql-23307的从库
    [root@mysql-1 ~]# mysql -uroot -P3307 -p123456 -S /data/mysql3307/mysql.sock -e "CHANGE MASTER TO MASTER_HOST='192.168.20.12', MASTER_PORT=3307, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123456';"
    [root@mysql-1 ~]# mysql -uroot -P3307 -p123456 -S /data/mysql3307/mysql.sock -e "start slave;"
    [root@mysql-1 ~]# mysql -uroot -P3307 -p123456 -S /data/mysql3307/mysql.sock -e "show slave status\G"
    
    
    2.mysql-23307成为mysql-13307的从库
    [root@mysql-2 ~]# mysql -uroot -P3307 -p123456 -S /data/mysql3307/mysql.sock -e "CHANGE MASTER TO MASTER_HOST='192.168.20.11', MASTER_PORT=3307, MASTER_AUTO_POSITION=1, MASTER_USER='repl', MASTER_PASSWORD='123456';"
    [root@mysql-2 ~]# mysql -uroot -P3307 -p123456 -S /data/mysql3307/mysql.sock -e "start slave;"
    [root@mysql-2 ~]# mysql -uroot -P3307 -p123456 -S /data/mysql3307/mysql.sock -e "show slave status\G"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    mysql-1的3307成为mysql-2的3307的从库。

    image-20220711215709916

    mysql-2的3307成为mysql-1的3307的从库。

    image-20220711215749308

    3.5.检查各个实例的主从状态

    mysql -uroot -P3306 -p123456 -S /data/mysql3306/mysql.sock -e "show slave status\G;"| egrep "Host|Yes"
    mysql -uroot -P3307 -p123456 -S /data/mysql3307/mysql.sock -e "show slave status\G;"| egrep "Host|Yes"
    mysql -uroot -P3308 -p123456 -S /data/mysql3308/mysql.sock -e "show slave status\G;"| egrep "Host|Yes"
    mysql -uroot -P3309 -p123456 -S /data/mysql3309/mysql.sock -e "show slave status\G;"| egrep "Host|Yes"
    
    • 1
    • 2
    • 3
    • 4

    image-20220711220528277

    4.部署Mycat

    4.1.部署Mycat

    1.安装java环境
    [root@mysql-1 ~]# yum -y install java
    
    2.安装mycat
    [root@mysql-1 ~]# tar xf Mycat-server-1.6.5-release-20180117003034-linux.tar.gz -C /data/
    [root@mysql-1 ~]# ll /data/mycat/
    总用量 12
    drwxr-xr-x 2 root root  190 711 22:14 bin
    drwxrwxrwx 2 root root    6 31 2016 catlet
    drwxrwxrwx 4 root root 4096 711 22:14 conf
    drwxr-xr-x 2 root root 4096 711 22:14 lib
    drwxrwxrwx 2 root root    6 117 2018 logs
    -rwxrwxrwx 1 root root  219 117 2018 version.txt
    
    3.配置环境变量
    [root@mysql-1 ~]# vim /etc/profile
    export MYCAT_HOME=/data/mycat
    export PATH=$MYCAT_HOME/bin:$PATH
    [root@mysql-1 ~]# source /etc/profile
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    4.2.Mycat文件介绍

    logs目录:
    	wrapper.log         #mycat启动日志
    	mycat.log           #mycat详细工作日志
    conf目录:
    	schema.xml      	#主配置文件(读写分离、高可用、分布式策略定制、节点控制)
    	server.xml		    #mycat软件本身相关的配置
    	rule.xml             #分片规则配置文件,记录分片规则列表、使用方法等
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    4.3.Mycat主配置文件简单介绍

    定义一个逻辑库,一般都和真实的数据库库名保持一致,在配置文件中定义了几个schema逻辑库,通过mycat连接之后就只能看见定义的这些逻辑库,其他未定义的数据库将看不到。

    <schema name="库名" checkSQLschema="false" sqlMaxLimit="100" dataNode="数据节点名"> 
    schema>  
    
    • 1
    • 2

    定义一个数据节点,在数据库节点中会定义数据库的主机以及对应的数据库库名。

    <dataNode name="主机节点名称" dataHost="数据库主机" database= "真实的数据库名称" />           
    
    • 1

    定义一个数据主机,在这里面主要是声明数据库的服务器IP、端口号、连接数据库的用户名密码等等信息,并且读写分离这种配置也是在数据主机中定义的。

            <dataHost name="数据主机名称" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1">    
                    <heartbeat>select user()heartbeat>  
            <writeHost host="主机名称" url="IP:端口号" user="用户名" password="密码"> 
                            <readHost host="主机名称" url="IP:端口号" user="用户名" password="密码" /> 
            writeHost> 
            dataHost>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    5.在mysql-1的3306主库中写入一些数据

    四套MySQL主从+双主的集群我们已经准备完毕了,接下来写入一些数据,然后实现使用Mycat完成读写分离以及高可用等操作。

    我们在mysql-1的3306主库上写入数据后,会同步到mysql-2的3306主库上,并且分别同步到各自主库关联的3308从库上,这是一套双主双从的复制集群,写入数据后方便我们后面实现读写分离和高可用。

    [root@mysql-1 ~]# mysql -uroot -P3306 -p123456 -S /data/mysql3306/mysql.sock
    create database db_1 character set utf8mb4;
    use db_1;
    create table bmxxb (
    	id int primary key auto_increment comment '部门ID',
    	bmmc varchar(10) not null comment '部门名称'
    ) comment '部门信息表';
    INSERT INTO bmxxb (id, bmmc) VALUES (1, '平台研发部'), (2, '技术运维部'),(3, '技术测试部'), (4, '销售部'), (5, '市场部'), (6, '人事部');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    6.使用Mycat实现读写分离以及高可用架构

    6.1.架构规划

    首先我们来实现一个简单的读写分离集群,使用mysql-1中的3306和3308这一对主从复制集群,基于Mycat实现读写分离集群。

    mysql-1的3306和mysql-2的3306是双主双从的复制集群,双主双从也就意味着数据是一样的,我们可以通过这个双主双从来实现一个高可用的读写分离集群,但是在高可用环境中,只会有一个主库在提供工作,另一个主库充当备用状态,当一个主库挂掉之后,备用主库接替故障主库的工作,当故障主库恢复后,处于备用状态。

    image-20220711224352635

    6.2.使用Mycat实现读写分离集群

    读写分离目前只使用mysql-1的3306和3308组成的主从复制集群,所有的写操作由3306主库进行处理,所有的读操作由3308从库进行处理。

    6.2.1.配置Mycat对主从复制集群实现读写分离

    1)编写Mycat读写分离配置文件

    [root@mysql-1 ~]# vim /data/mycat/conf/schema.xml 
    
    DOCTYPE mycat:schema SYSTEM "schema.dtd">  
    <mycat:schema xmlns:mycat="http://io.mycat/">
            <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="sh1">schema>
    	  	
            <dataNode name="sh1" dataHost="mysql-1" database= "db_1" />          
    
            <dataHost name="mysql-1" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1">    
                    <heartbeat>select user()heartbeat>  
                    <writeHost host="db1" url="192.168.20.11:3306" user="root" password="123456">
                            <readHost host="db2" url="192.168.20.11:3308" user="root" password="123456" />
                    writeHost> 
            dataHost>  
    
    mycat:schema>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2)配置文件解释

    	     //定义一个逻辑库,库名叫TESTDB,关联的dataNode为sh1
    		<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="sh1">schema>  
    		
    		//定义一个主机节点,名称为sh1,关联的dataHost为mysql-1,关联的数据库是db_1,关联的数据库要真实存在
            <dataNode name="sh1" dataHost="mysql-1" database= "db_1" />          
    
    		//定义一个数据主机,名称为mysql-1,被主机节点关联
            <dataHost name="mysql-1" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1">    
                    <heartbeat>select user()heartbeat>  
                	//定义一个写主机,所有的写操作都路由到这个数据库节点上处理,对应的是主从复制中的主库
                    <writeHost host="db1" url="192.168.20.11:3306" user="root" password="123456">
                        	//定义一个读主机,所有的读操作都路由到这个数据库节点上处理,对应的是主从复制中的从库
                            <readHost host="db2" url="192.168.20.11:3308" user="root" password="123456" />
                    writeHost> 
            dataHost>  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    3)启动Mycat

    [root@mysql-1 ~]# mycat start 
    Starting Mycat-server...
    
    [root@mysql-1 conf]# netstat -lnpt | grep java
    tcp        0      0 127.0.0.1:32000         0.0.0.0:*               LISTEN      6508/java           
    tcp6       0      0 :::1984                 :::*                    LISTEN      6508/java           
    tcp6       0      0 :::8066                 :::*                    LISTEN      6508/java           
    tcp6       0      0 :::37891                :::*                    LISTEN      6508/java           
    tcp6       0      0 :::9066                 :::*                    LISTEN      6508/java           
    tcp6       0      0 :::35853                :::*                    LISTEN      6508/java  
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    Mycat启动成功,Mycat的8066端口是程序连接的端口,9066端口是管理端口。

    6.2.1.测试Mycat实现的读写分离集群

    通过Mycat连接数据库。

    1)读操作

    读操作会落在从库db2上,server_id为8。

    [root@mysql-1 ~]# mysql -uroot -p123456 -h 192.168.20.11 -P 8066
    mysql> select @@server_id;
    +-------------+
    | @@server_id |
    +-------------+
    |           8 |
    +-------------+
    1 row in set (0.13 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2)写操作

    读操作会落在主库db1上,server_id为6。

    mysql> begin; select @@server_id;
    Query OK, 0 rows affected (0.00 sec)
    
    +-------------+
    | @@server_id |
    +-------------+
    |           6 |
    +-------------+
    1 row in set (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    6.3.使用Mycat实现读写分离高可用集群

    6.3.1.Mycat读写分离高可用架构集群概念

    在上面,我们通过Mycat实现了读写分离,但是当主库挂掉了,从库也就无法进行读操作了,因为读写分离集群,要保证读和写对应的数据库都是正常的,否则都不能操作,为了避免主库宕机造成系统崩溃,接下来我们去实现Mycat读写分离的高可用架构。

    image-20220712000508979

    Mycat读写分离高可用架构,其实就是双主的架构,双主复制集群中,最少需要4台服务器,4个MySQL实例,每个主从集群中最少包含一主一从,然后两个主之间相互复制,双主复制就可以保证4个MySQL实例中的数据几乎都是一样的。

    在高可用模式下,多主只会有其中一个主在提供工作,另一个主充当备用主库的角色,当主库故障后,备用主库会自动切换为主库进行工作,当主库故障后,该主库对应的从库也将停止工作,此时正在工作的也就是备用主库和对应的从库,在高可用架构中,双主对应的所有从库都会工作,主库只有一个在工作。

    高可用模式下,当主库故障修复后,会充当备用角色。

    双主模式下,在mycat的配置文件中,哪一对主从先书写的,顺序从上到下,最上面的将会成为提供服务的主库,下面的主库充当备用角色。

    6.3.2.配置Mycat读写分离高可用集群

    高可用集群其实就是多加了一组读写主机而已,但是多组读写主机的数据一定要保证是一致的,也就是互为主从的架构,多组读写中,只要主库不故障,从库将会从始至终的提供服务,如果对应的主库故障了,从库也就不会提供服务了。

    [root@mysql-1 ~]# vim /data/mycat/conf/schema.xml
    
    DOCTYPE mycat:schema SYSTEM "schema.dtd">
    <mycat:schema xmlns:mycat="http://io.mycat/">
    
            <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="sh1">schema>
    
            <dataNode name="sh1" dataHost="mysql-1" database= "db_1" />
    
            <dataHost name="mysql-1" maxCon="1000" minCon="10" balance="1"  writeType="0" dbType="mysql"  dbDriver="native" switchType="1">
                    <heartbeat>select user()heartbeat>
                    <writeHost host="db1" url="192.168.20.11:3306" user="root" password="123456">
                            <readHost host="db2" url="192.168.20.11:3308" user="root" password="123456" />
                    writeHost> 
                    
                    <writeHost host="db3" url="192.168.20.12:3306" user="root" password="123456">
                            
                            <readHost host="db4" url="192.168.20.12:3308" user="root" password="123456" />
                    writeHost> 
            dataHost>  
    
    mycat:schema>       
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    重启mycat。

    [root@mysql-1 ~]# mycat restart
    Stopping Mycat-server...
    Stopped Mycat-server.
    Starting Mycat-server...
    
    • 1
    • 2
    • 3
    • 4
    6.3.3.测试高可用的读写分离集群

    1)读操作

    两个从库都负责读的操作,只要这两个从库对应的主库不故障,这两个从库会从始至终的提供读操作,可以看到路由的很均衡,几乎一次是db2从库处理数据,一次是db4从库处理数据。

    [root@mysql-1 ~]# mysql -uroot -p123456 -h 192.168.20.11 -P 8066
    mysql> select @@server_id;
    +-------------+
    | @@server_id |
    +-------------+
    |           18 |
    +-------------+
    1 row in set (0.13 sec)
    
    mysql> select @@server_id;
    +-------------+
    | @@server_id |
    +-------------+
    |           6 |
    +-------------+
    1 row in set (0.01 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2)写操作

    正常情况下,db1数据库在配置文件的最上方,只要db1不故障,所有的写操作都有db1处理,db3主库会一直处于备用状态。

    mysql> begin; select @@server_id;
    Query OK, 0 rows affected (0.00 sec)
    
    +-------------+
    | @@server_id |
    +-------------+
    |           6 |
    +-------------+
    1 row in set (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    3)db1主库故障无法承担写的操作 此时db3主库切换为主库 承担写操作

    1.db1主库故障
    [root@mysql-1 ~]# systemctl stop mysqld3306
    
    2.此时db3会去处理所有的读操作,保证服务不中断
    mysql> begin; select @@server_id;
    Query OK, 0 rows affected (0.00 sec)
    
    +-------------+
    | @@server_id |
    +-------------+
    |          16 |
    +-------------+
    1 row in set (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    当db1修复后,不会抢占db3成为正在工作的主库,而是处于备用状态。

    1.修复db1
    [root@mysql-1 ~]# systemctl start mysqld3306
    
    2.提供工作的依旧是db3
    mysql> begin; select @@server_id;
    Query OK, 0 rows affected (0.00 sec)
    
    +-------------+
    | @@server_id |
    +-------------+
    |          16 |
    +-------------+
    1 row in set (0.00 sec)
    
    3.读操作也会均匀的分配到两个从库上
    mysql> select @@server_id;
    +-------------+
    | @@server_id |
    +-------------+
    |           6 |
    +-------------+
    1 row in set (0.00 sec)
    
    mysql> select @@server_id;
    +-------------+
    | @@server_id |
    +-------------+
    |          18 |
    +-------------+
    1 row in set (0.00 sec)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
  • 相关阅读:
    SpringMVC学习篇(六)
    基于单片机的超声波探伤仪设计
    idea默认带的equals和hashcode引起的bug
    学习-Java输入输出之对象IO流之序列化一个对象
    [机缘参悟-77]:深度思考-《天道》中强势文化、弱势文化与人的行为模式的关系
    dropout
    Java修饰符 abstract,static,final 的区别详解
    代码随想录算法训练营第三天|203、707、206
    毕业设计:SpringBoot+Vue+Element的校内跑腿平台
    多线程入门总结
  • 原文地址:https://blog.csdn.net/weixin_44953658/article/details/136291069