验证可用性

  1. 配置MySQL Router。

    1. 编辑文件。
      1
      vim /etc/mysqlrouter/mysqlrouter.conf
      
    2. 替换如下内容。
       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
      [DEFAULT]
      logging_folder = /var/log/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:basic_failover]
      # Router地址
      bind_address = 192.168.53.22
      # Router端口
      bind_port = 7001
      routing_strategy = first-available
      # 目标服务器
      destinations = 192.168.53.22:3306,192.168.53.22:3307
      connect_timeout = 2
      
      [routing:load_balance]
      # Router地址
      bind_address = 192.168.53.22
      # Router端口
      bind_port = 7002
      routing_strategy = round-robin
      # 目标服务器
      destinations = 192.168.53.22:3306,192.168.53.22:3307,192.168.53.22:3308
      connect_timeout = 1
      
    3. “Esc”键,输入:wq!,按“Enter”保存并退出编辑。
    4. 启动MySQL Router。
      1. 查询mysqlrouter的进程ID。
        1
        ps -ef|grep mysqlrouter
        

      2. 关闭mysqlrouter的进程。
        1
        kill -9 72890
        
      3. 启动mysqlrouter。
        1
        mysqlrouter &
        
      4. 确认是否启动成功。
        1
        2
        netstat -an|grep 7001
        netstat -an|grep 7002
        

        回显内容与图片内容一致,则表示已正常启动。

        当192.168.53.22:3306服务可用时,对于7001端口的请求,会全部发送到192.168.53.22:3306。对于7002的端口的请求,会轮询发送给192.168.53.22:3306,192.168.53.22:3307,192.168.53.22:3308。验证MySQL Router读写分离及负载均衡中步骤3和步骤4已验证。

  2. 模拟从库1服务停用了,主库、从库2服务正常,读写路由情况。

    1. 登录数据库从库1。
      1
      /usr/local/mysql/bin/mysql -uroot -p123456 -S /data/mysql/run/mysqls.sock
      
    2. 关闭数据库。
      1
      shutdown;
      
    3. 执行读脚本。
      1
      sh /home/read_7002.sh
      

      从库1关闭的情况下,发送到7002端口的读请求会被轮询的发送到主库和从库2服务,符合预期。

    4. 执行写脚本。
      1. 编辑文件。
        1
        vim /home/write_7001.sh
        
      2. 替换如下内容。
        1
        2
        3
        4
        5
        #!/bin/bash
        for i in {2001..3000}
        do
        /usr/local/mysql/bin/mysql -uroot -p123456 -P7001 -h192.168.53.22 -Dsysbench -e "insert into test1(id,report_hostname) values($i,@@report_host)"
        done
        
      3. “Esc”键,输入:wq!,按“Enter”保存并退出编辑。
      4. 执行写请求脚本。
        1
        sh /home/write_7001.sh
        
      5. 确认测试数据。
        1
        /usr/local/mysql/bin/mysql -uroot -p123456 -P7001 -h192.168.53.22 -Dsysbench -e "select * from test1"
        

        从上图可以发现,只要是7001端口的写请求,都会发送到第一个目标192.168.53.22:3306 master(主库)执行,符合预期。

  3. 模拟从库1、从库2服务都停用了,主库服务正常,读写路由情况。

    1. 登录数据库从库2。
      1
      /usr/local/mysql/bin/mysql -uroot -p123456 -S /data/mysql/run/mysqls2.sock
      
    2. 关闭数据库。
      1
      shutdown;
      
    3. 执行读脚本。
      1
      sh /home/read_7002.sh
      

      从库1、从库2都已经关闭的情况下,发送到7002端口的读请求只会被发送到主库服务,符合预期。

    4. 执行写脚本。
      1. 编辑文件。
        1
        vim /home/write_7001.sh
        
      2. 替换如下内容。
        1
        2
        3
        4
        5
        #!/bin/bash
        for i in {3001..4000}
        do
        /usr/local/mysql/bin/mysql -uroot -p123456 -P7001 -h192.168.53.22 -Dsysbench -e "insert into test1(id,report_hostname) values($i,@@report_host)"
        done
        
      3. “Esc”键,输入:wq!,按“Enter”保存并退出编辑。
      4. 执行写请求脚本。
        1
        sh /home/write_7001.sh
        
      5. 确认测试数据。
        1
        /usr/local/mysql/bin/mysql -uroot -p123456 -P7001 -h192.168.53.22 -Dsysbench -e "select * from test1"
        

        从上图可以发现,只要是7001端口的写请求,都会发送到第一个目标192.168.53.22:3306 master(主库)执行,符合预期。

  4. 模拟主库服务停用了,从库1、从库2服务正常,读写路由情况。

    1. 恢复启动从库1,从库2。
      1
      2
      /usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf-slave &
      /usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf-slave-2 &
      
    2. 搭建主从关系。

      MySQL主从复制方案请参见《MySQL 主从复制部署指南》中“半同步复制”、“并行复制”和“GTID同步方式”章节。我们会看到从库1、从库2的数据已从主库同步过来,与主库保持一致。

    3. 关闭master(主库)。
      1
      2
      /usr/local/mysql/bin/mysql -uroot -p123456 -S /data/mysql/run/mysqlm.sock
      shutdown;
      
    4. 执行读脚本。
      1
      sh /home/read_7001.sh
      

      从上图可以发现,只要对于7001端口的读请求,会全部发送到第一个目标192.168.53.22:3306 master(主库),但是主库已经被关闭了,所以读请求会自动发送到从库1(192.168.53.22:3307)。

    5. 执行读脚本。
      1
      sh /home/read_7002.sh
      

      从上图可以发现,只要将读请求发送到7002端口,请求会被轮询的发送到3个MySQL服务。但是主库已经被关闭了,所以请求会被发送到从库1(192.168.53.22:3307)和从库2(192.168.53.22:3308)。

    6. 执行写脚本。
      1. 编辑文件。
        1
        vim /home/write_7001.sh
        
      2. 替换如下内容。
        1
        2
        3
        4
        5
        #!/bin/bash
        for i in {4001..5000}
        do
        /usr/local/mysql/bin/mysql -uroot -p123456 -P7001 -h192.168.53.22 -Dsysbench -e "insert into test1(id,report_hostname) values($i,@@report_host)"
        done
        
      3. “Esc”键,输入:wq!,按“Enter”保存并退出编辑。
      4. 执行写请求脚本。
        1
        sh /home/write_7001.sh
        
      5. 确认测试数据。
        1
        /usr/local/mysql/bin/mysql -uroot -p123456 -P7001 -h192.168.53.22 -Dsysbench -e "select * from test1"
        

        从以上实验可以看出主库(192.168.53.22:3306)宕机后,7001端口所有的请求都回到从库(192.168.53.22:3307)上。

        由于写入数据,当前从库1上,从库2无法同步,我们将从库1设置为主库,保证原从库1,从库2数据同步。

    7. 搭建从库1,从库2为主从关系。

      MySQL主从复制方案请参见《MySQL 主从复制部署指南》中“半同步复制”、“并行复制”和“GTID同步方式”章节。

      搭建成功后,会看到从库2的数据已同步过来,与从库1(现主库)保持一致。

    8. 恢复启动原主库192.168.53.22:3306。
      1
      /usr/local/mysql/bin/mysqld_safe --defaults-file=/etc/my.cnf-master &
      
    9. 原主库设置为从库。

      MySQL主从复制方案请参见《MySQL 主从复制部署指南》中“半同步复制”、“并行复制”和“GTID同步方式”章节。

      设置成功后,会看到原主库(3306)的数据已从现主库(3307)同步过来,与现主库保持一致。最终,新的主从关系搭建成功,192.168.53.22:3307是主库,192.168.53.22:3308是从库1,192.168.53.22:3306是从库2。

  5. MySQL Router读写路由验证。

    1. 执行读脚本。
      1
      sh /home/read_7001.sh
      

      从上图可以发现,只要对于7001端口的读请求,会全部发送到目标192.168.53.22:3307 (主库),符合预期。

    2. 执行读脚本。
      1
      sh /home/read_7002.sh
      

      从上图可以发现,只要将读请求发送到7002端口,请求会被轮询的发送到3个MySQL服务,符合预期。

    3. 执行写脚本。
      1. 编辑文件。
        1
        vim /home/write_7001.sh
        
      2. 替换如下内容。
        1
        2
        3
        4
        5
        #!/bin/bash
        for i in {5001..6000}
        do
        /usr/local/mysql/bin/mysql -uroot -p123456 -P7001 -h192.168.53.22 -Dsysbench -e "insert into test1(id,report_hostname) values($i,@@report_host)"
        done
        
      3. “Esc”键,输入:wq!,按“Enter”保存并退出编辑。
      4. 执行写请求脚本。
        1
        sh /home/write_7001.sh
        
      5. 确认测试数据。
        1
        /usr/local/mysql/bin/mysql -uroot -p123456 -P7001 -h192.168.53.22 -Dsysbench -e "select * from test1"
        

        从上图可以发现,7001端口的写请求都会在目标192.168.53.22:3307 (主库)执行。符合预期。

  6. 如果此时重启MySQL Router服务,7001端口的请求只会路由到192.168.53.22:3306。因为MySQL Router第一次收到客户端请求时,会将请求转发给destinations列表中的第一个目标。验证如下:

    1. 查询mysqlrouter的进程ID。
      1
      ps -ef|grep mysqlrouter
      

    2. 关闭mysqlrouter的进程。
      1
      kill -9 72890
      
    3. 启动mysqlrouter。
      1
      mysqlrouter &
      
    4. 确认是否启动成功。
      1
      2
      netstat -an|grep 7001
      netstat -an|grep 7002
      

      回显内容与图片内容一致,则表示已正常启动。

    5. 执行读请求脚本。
      1
      sh /home/read_7001.sh
      

      从上图可以发现,7001端口所有的操作都在192.168.53.22:3306 (从库2)执行,符合预期。

      重启MySQL Router后,此时192.168.53.22:3306在主从复制关系中依然是slave,但只有他接受读写请求,实际上是以192.168.53.22:3306作为主从复制的master,这次MySQL Router的重启已经破坏了主从复制的一致性,因此这种场景下需要重新搭建主从关系。或者修改MySQL Router配置文件,7001端口的请求转发给destinations列表中的第一个目标,所以将192.168.53.22:3307放到第一目标位即可。