案例:数据读写分离

1 问题

  1. 搭建一主一从结构
  2. 配置MyCAT服务器
  3. 配置读写分离
  4. 测试配置

2 方案

准备新的虚拟机,如表所示

mysql数据库读写分离_mysql

准备虚拟机

实验拓扑如图-2所示

mysql数据库读写分离_mysql_02

图-2

3 步骤

实现此案例需要按照如下步骤进行。

步骤一:搭建一主一从结构

因为数据的查询和存储分别访问不同的数据库服务器,所以要通过主从同步来保证负责读访问与负责写访问 数据库服务的数据一致。

1)配置主数据库服务器

//启用binlog日志
 [root@mysql56 ~]# vim /etc/my.cnf.d/mysql-server.cnf
 [mysqld]
 server-id=56
 log-bin=mysql56
 :wq
 //重启数据库服务
 [root@mysql56 ~]# systemctl restart mysqld
 
 //用户授权
 [root@mysql56 ~]# mysql
 mysql> create user repluser@"%" identified by  "123qqq...A";
 mysql> grant replication slave on  *.* to  repluser@"%" ;
 
 //查看日志信息
 mysql> show master status;
 +----------------+----------+--------------+------------------+-------------------+
 | File           | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
 +----------------+----------+--------------+------------------+-------------------+
 | mysql56.000001 |      667 |              |                  |                   |
 +----------------+----------+--------------+------------------+-------------------+
 1 row in set (0.00 sec)

2)配置从数据库服务器

//指定server-id 并重启数据库服务
 [root@mysql57 ~]# yum -y install  mysql-server mysql
 [root@mysql57 ~]# systemctl  start mysqld
 [root@mysql57 ~]# vim /etc/my.cnf.d/mysql-server.cnf
 [mysqld]
 server-id=57
 :wq
 //重启数据库服务
 [root@mysql57 ~]# systemctl  restart mysqld
 
 //管理员登陆,指定主服务器信息
 [root@mysql57 ~]# mysql
 mysql> change master to 
 master_host="192.168.88.56", 
 master_user="repluser",
 master_password="123qqq...A",
 master_log_file="mysql56.000001",
 master_log_pos=667;
 
 //启动slave进程
 mysql> start slave;
 
 //查看状态信息
 mysql> show slave status \G
 *************************** 1. row ***************************
                Slave_IO_State: Waiting for source to send event
                   Master_Host: 192.168.88.56
                   Master_User: repluser
                   Master_Port: 3306
                 Connect_Retry: 60
               Master_Log_File: mysql56.000001
           Read_Master_Log_Pos: 667
                Relay_Log_File: mysql57-relay-bin.000002
                 Relay_Log_Pos: 322
         Relay_Master_Log_File: mysql56.000001
              Slave_IO_Running: Yes   //IO线程
             Slave_SQL_Running: Yes   //SQL线程
               Replicate_Do_DB: 
           Replicate_Ignore_DB: 
            Replicate_Do_Table: 
        Replicate_Ignore_Table: 
       Replicate_Wild_Do_Table: 
   Replicate_Wild_Ignore_Table: 
                    Last_Errno: 0
                    Last_Error: 
                  Skip_Counter: 0
           Exec_Master_Log_Pos: 667
               Relay_Log_Space: 533
               Until_Condition: None
                Until_Log_File: 
                 Until_Log_Pos: 0
            Master_SSL_Allowed: No
            Master_SSL_CA_File: 
            Master_SSL_CA_Path: 
               Master_SSL_Cert: 
             Master_SSL_Cipher: 
                Master_SSL_Key: 
         Seconds_Behind_Master: 0
 Master_SSL_Verify_Server_Cert: No
                 Last_IO_Errno: 0
                 Last_IO_Error: 
                Last_SQL_Errno: 0
                Last_SQL_Error: 
   Replicate_Ignore_Server_Ids: 
              Master_Server_Id: 56
                   Master_UUID: e0ab8dc4-0109-11ee-87e7-525400ad7ed3
              Master_Info_File: mysql.slave_master_info
                     SQL_Delay: 0
           SQL_Remaining_Delay: NULL
       Slave_SQL_Running_State: Replica has read all relay log; waiting for more updates
            Master_Retry_Count: 86400
                   Master_Bind: 
       Last_IO_Error_Timestamp: 
      Last_SQL_Error_Timestamp: 
                Master_SSL_Crl: 
            Master_SSL_Crlpath: 
            Retrieved_Gtid_Set: 
             Executed_Gtid_Set: 
                 Auto_Position: 0
          Replicate_Rewrite_DB: 
                  Channel_Name: 
            Master_TLS_Version: 
        Master_public_key_path: 
         Get_master_public_key: 0
             Network_Namespace: 
 1 row in set, 1 warning (0.00 sec)

步骤二:配置mycat服务器

1)从真机拷贝软件到mycat58主机

[root@server1 ~]# scp /linux-soft/s3/mycat2-1.21-release-jar-with-dependencies.jar  root@192.168.88.58:/root/
 [root@server1 ~]# scp /linux-soft/s3/mycat2-install-template-1.21.zip  root@192.168.88.58:/root/

2)安装mycat软件

//安装jdk

[root@mycat58 upload]# yum -y install java-1.8.0-openjdk.x86_64

//安装解压命令

[root@mycat58 upload]# which unzip || yum -y  install unzip

//安装mycat

[root@mycat58 upload]# unzip mycat2-install-template-1.21.zip
 [root@mycat58 upload]# mv mycat /usr/local/

//安装依赖

[root@mycat58 upload]# cp mycat2-1.21-release-jar-with-dependencies.jar  /usr/local/mycat/lib/

//修改权限

[root@mycat58 upload]# chmod -R 777 /usr/local/mycat/

3)定义客户端连接mycat服务使用用户及密码:

[root@mycat58 ~]# vim  /usr/local/mycat/conf/users/root.user.json
 {
         "dialect":"mysql",
         "ip":null,
         "password":"654321", 密码
         "transactionType":"proxy",
         "username":"mycat" 用户名
 }
 :wq

4)定义连接的数据库服务器

[root@mycat58 ~]# vim  /usr/local/mycat/conf/datasources/prototypeDs.data
 {
         "dbType":"mysql",
         "idleTimeout":60000,
         "initSqls":[],
         "initSqlsGetConnection":true,
         "instanceType":"READ_WRITE",
         "maxCon":1000,
         "maxConnectTimeout":3000,
         "maxRetryCount":5,
         "minCon":1,
         "name":"prototypeDs",
         "password":"123456", 密码
         "type":"JDBC",
         "url":"jdbc:mysql://localhost:3306/mysql?useUnicode=true&serverTimeznotallow=Asia/Shanghai&characterEncoding=UTF-8", 连接本机的数据库服务
 
         "user":"plj", 用户名
         "weight":0
 }
 :wq

5)在mycat58主机运行数据库服务

[root@mycat58 ~]# yum -y  install  mysql-server  mysql  安装软件
 [root@mycat58 ~]# systemctl start mysqld  //启动服务
 [root@mycat58 ~]# mysql   //连接服务
 mysql> create user plj@"%" identified by "123456";  //创建plj用户
 mysql> grant all on *.* to plj@"%" ;   //授予权限
 mysql> exit  //断开连接
 Bye
 [root@mycat58 ~]#

6)启动mycat服务

//查看帮助
 [root@mycat58 ~]# /usr/local/mycat/bin/mycat help
 Usage: /usr/local/mycat/bin/mycat { console | start | stop | restart | status | dump }
 //启动服务
 [root@mycat58 ~]# /usr/local/mycat/bin/mycat start
 Starting mycat2...
 //半分钟左右 能看到端口
 [root@mycat58 ~]# netstat  -utnlp  | grep 8066
 tcp6       0      0 :::8066  :::*       LISTEN      57015/java          
 [root@mycat58 ~]#

7) 连接mycat服务

[root@mycat58 ~]# mysql -h127.0.0.1 -P8066 -umycat -p654321
 mysql> show databases;
 +--------------------+
 | `Database`         |
 +--------------------+
 | information_schema |
 | mysql              |
 | performance_schema |
 +--------------------+
 3 rows in set (0.11 sec)
 Mysql>

步骤三:配置读写分离

1)添加数据源:连接mycat服务后做如下操作

//连接mycat服务
 [root@mycat58 ~]# mysql -h127.0.0.1 -P8066 -umycat -p654321
 
 //添加mysql56数据库服务器
 MySQL> /*+ mycat:createdatasource{
 "name":"whost56", 
 "url":"jdbc:mysql://192.168.88.56:3306",
 "user":"plja","password":"123456"
 }*/;
 
 //添加mysql57数据库服务器
 Mysql>/*+ mycat:createdatasource{
 "name":"rhost57", 
 "url":"jdbc:mysql://192.168.88.57:3306",
 "user":"plja",
 "password":"123456"
 }*/;
 
 //查看数据源
 mysql> /*+mycat:showDataSources{}*/ \G
 *************************** 1. row ***************************
                    NAME: whost56
                USERNAME: plja
                PASSWORD: 123456
                 MAX_CON: 1000
                 MIN_CON: 1
               EXIST_CON: 0
                 USE_CON: 0
         MAX_RETRY_COUNT: 5
     MAX_CONNECT_TIMEOUT: 30000
                 DB_TYPE: mysql
                     URL: jdbc:mysql://192.168.88.56:3306?serverTimeznotallow=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&autoRecnotallow=true
                  WEIGHT: 0
                INIT_SQL: 
 INIT_SQL_GET_CONNECTION: true
           INSTANCE_TYPE: READ_WRITE
            IDLE_TIMEOUT: 60000
                  DRIVER: {
         CreateTime:"2023-06-02 17:01:14",
         ActiveCount:0,
         PoolingCount:0,
         CreateCount:0,
         DestroyCount:0,
         CloseCount:0,
         ConnectCount:0,
         Connections:[
         ]
 }
                    TYPE: JDBC
                IS_MYSQL: true
 *************************** 2. row ***************************
                    NAME: rhost57
                USERNAME: plja
                PASSWORD: 123456
                 MAX_CON: 1000
                 MIN_CON: 1
               EXIST_CON: 0
                 USE_CON: 0
         MAX_RETRY_COUNT: 5
     MAX_CONNECT_TIMEOUT: 30000
                 DB_TYPE: mysql
                     URL: jdbc:mysql://192.168.88.57:3306?useUnicode=true&serverTimeznotallow=Asia/Shanghai&characterEncoding=UTF-8&autoRecnotallow=true
                  WEIGHT: 0
                INIT_SQL: 
 INIT_SQL_GET_CONNECTION: true
           INSTANCE_TYPE: READ_WRITE
            IDLE_TIMEOUT: 60000
                  DRIVER: {
         CreateTime:"2023-06-02 17:01:14",
         ActiveCount:0,
         PoolingCount:0,
         CreateCount:0,
         DestroyCount:0,
         CloseCount:0,
         ConnectCount:0,
         Connections:[
         ]
 }
                    TYPE: JDBC
                IS_MYSQL: true
 *************************** 3. row ***************************
                    NAME: prototypeDs
                USERNAME: plj
                PASSWORD: 123456
                 MAX_CON: 1000
                 MIN_CON: 1
               EXIST_CON: 0
                 USE_CON: 0
         MAX_RETRY_COUNT: 5
     MAX_CONNECT_TIMEOUT: 3000
                 DB_TYPE: mysql
                     URL: jdbc:mysql://localhost:3306/mysql?serverTimeznotallow=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&autoRecnotallow=true
                  WEIGHT: 0
                INIT_SQL: 
 INIT_SQL_GET_CONNECTION: true
           INSTANCE_TYPE: READ_WRITE
            IDLE_TIMEOUT: 60000
                  DRIVER: {
         CreateTime:"2023-06-02 17:01:14",
         ActiveCount:0,
         PoolingCount:0,
         CreateCount:0,
         DestroyCount:0,
         CloseCount:0,
         ConnectCount:0,
         Connections:[
         ]
 }
                    TYPE: JDBC
                IS_MYSQL: true
 3 rows in set (0.00 sec)
 mysql>exit  //断开连接
 
 //添加的数据源以文件的形式保存在安装目录下
 [root@mycat58 conf]# ls /usr/local/mycat/conf/datasources/
 prototypeDs.datasource.json  rhost57.datasource.json  whost56.datasource.json
 [root@mycat58 conf]#

2)配置数据库服务器添加plja用户

//在master服务器添加

[root@mysql56 ~]# mysql 
 mysql> create user plja@"%" identified by "123456";
 mysql> grant all on *.* to  plja@"%";
 mysql>exit

//在slave服务器查看是否同步成功

[root@mysql57 ~]# mysql -e 'select user , host from mysql.user where user="plja"'
 +------+------+
 | user | host |
 +------+------+
 | plja | %    |
 +------+------+
 [root@mysql57 ~]#

3)创建集群

//连接mycat服务

[root@mycat58 ~]# mysql -h127.0.0.1 -P8066 -umycat -p654321

//创建集群

mysql>/*!mycat:createcluster{
 "name":"rwcluster",
 "masters":["whost56"],
 "replicas":["rhost57"]
 }*/ ;
 Mysql>

//查看集群信息

mysql> /*+ mycat:showClusters{}*/ \G
 *************************** 1. row ***************************
              NAME: rwcluster
       SWITCH_TYPE: SWITCH
 MAX_REQUEST_COUNT: 2000
              TYPE: BALANCE_ALL
          WRITE_DS: whost56
           READ_DS: whost56,rhost57
           WRITE_L: io.mycat.plug.loadBalance.BalanceRandom$1
            READ_L: io.mycat.plug.loadBalance.BalanceRandom$1
         AVAILABLE: true
 *************************** 2. row ***************************
              NAME: prototype
       SWITCH_TYPE: SWITCH
 MAX_REQUEST_COUNT: 200
              TYPE: BALANCE_ALL
          WRITE_DS: prototypeDs
           READ_DS: prototypeDs
           WRITE_L: io.mycat.plug.loadBalance.BalanceRandom$1
            READ_L: io.mycat.plug.loadBalance.BalanceRandom$1
         AVAILABLE: true
 2 rows in set (0.00 sec)
 
 mysql>

//创建的集群以文件的形式保存在目录下

[root@mycat58 conf]# ls /usr/local/mycat/conf/clusters/
 prototype.cluster.json  rwcluster.cluster.json

4)指定主机角色

//修改master角色主机仅负责写访问

[root@mycat58 ~]# vim /usr/local/mycat/conf/datasources/whost56.datasource.json
 {
         "dbType":"mysql",
         "idleTimeout":60000,
         "initSqls":[],
         "initSqlsGetConnection":true,
         "instanceType":"WRITE", #仅负责写访问
         "logAbandoned":true,
         "maxCon":1000,
         "maxConnectTimeout":30000,
         "maxRetryCount":5,
         "minCon":1,
         "name":"whost56",
         "password":"123456",
         "queryTimeout":0,
         "removeAbandoned":false,
         "removeAbandonedTimeoutSecond":180,
         "type":"JDBC",
         "url":"jdbc:mysql://192.168.88.56:3306?serverTimeznotallow=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&autoRecnotallow=true",
         "user":"plja",
         "weight":0
 }
 :wq

//修改slave角色主机仅负责读访问

[root@mycat58 ~]# vim /usr/local/mycat/conf/datasources/rhost57.datasource.json
 {
         "dbType":"mysql",
         "idleTimeout":60000,
         "initSqls":[],
         "initSqlsGetConnection":true,
         "instanceType":"READ",  #仅负责读访问
         "logAbandoned":true,
         "maxCon":1000,
         "maxConnectTimeout":30000,
         "maxRetryCount":5,
         "minCon":1,
         "name":"rhost57",
         "password":"123456",
         "queryTimeout":0,
         "removeAbandoned":false,
         "removeAbandonedTimeoutSecond":180,
         "type":"JDBC",
         "url":"jdbc:mysql://192.168.88.57:3306?serverTimeznotallow=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&autoRecnotallow=true",
         "user":"plja",
         "weight":0
 }
 :wq

5)修改读策略

[root@mycat58 ~]# vim /usr/local/mycat/conf/clusters/rwcluster.cluster.json 
 {
         "clusterType":"MASTER_SLAVE",
         "heartbeat":{
                 "heartbeatTimeout":1000,
                 "maxRetryCount":3,
                 "minSwitchTimeInterval":300,
                 "showLog":false,
                 "slaveThreshold":0.0
         },
         "masters":[
                 "whost56"
         ],
         "maxCon":2000,
         "name":"rwcluster",
         "readBalanceType":"BALANCE_ALL_READ", #把读访问平均分配给read角色的主机
         "replicas":[
                 "rhost57"
         ],
         "switchType":"SWITCH"
 }
 :wq

//重启mycat服务

[root@mycat58 ~]# /usr/local/mycat/bin/mycat restart
 Stopping mycat2...
 Stopped mycat2.
 Starting mycat2...
 [root@mycat58 ~]#

步骤四:测试配置

思路如下:

  1. 连接mycat服务建库
  2. 指定存储数据使用的集群
  3. 连接mycat服务建表
  4. 客户端连接mycat服务执行select 或 insert

具体操作如下:

//连接mycat服务

[root@mycat58 ~]# mysql -h127.0.0.1 -P8066 -umycat -p654321

//创建存储数据的库

mysql> create database testdb;
 mysql> exit
 Bye

//指定库存储数据使用的集群

[root@mycat58 ~]# vim /usr/local/mycat/conf/schemas/testdb.schema.json
 {
         "customTables":{},
         "globalTables":{},
         "normalProcedures":{},
         "normalTables":{},
         "schemaName":"testdb",
         "targetName":"rwcluster", 添加此行(之前创建的集群名rwcluster)
         "shardingTables":{},
         "views":{}
 }
 :wq

//重启mycat服务

[root@mycat58 ~]# /usr/local/mycat/bin/mycat restart
 Stopping mycat2...
 Stopped mycat2.
 Starting mycat2...
 [root@mycat58 ~]#

//客户端连接mycat服务

[root@client50 ~]# mysql -h192.168.88.58 -P8066 -umycat -p654321

//建表

mysql> create table testdb.user (name varchar(10) , password varchar(10));

//插入记录

mysql> insert into  testdb.user values("yaya","123456");

//查看表记录

mysql> select  * from testdb.user;
 +------+----------+
 | name | password |
 +------+----------+
 | yaya | 123456   |
 +------+----------+
 1 row in set (0.01 sec)
 mysql> exit

测试读写分离

//在slave服务器本机插入记录,使其与master服务器的数据不一样

[root@mysql57 ~]# mysql -e 'insert into testdb.user values ("yayaA","654321")'
 [root@mysql57 ~]# mysql -e 'select * from testdb.user'
 +-------+----------+
 | name  | password |
 +-------+----------+
 | yaya  | 123456   |
 | yayaA | 654321   |
 +-------+----------+
 [root@mysql57 ~]#

//主服务器数据不变

[root@mysql56 ~]# mysql -e 'select * from testdb.user'
 +------+----------+
 | name | password |
 +------+----------+
 | yaya | 123456   |
 +------+----------+

//binlog日志偏移量不变

[root@mysql56 ~]# mysql -e 'show master status'
 +----------------+----------+--------------+------------------+-------------------+
 | File           | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
 +----------------+----------+--------------+------------------+-------------------+
 | mysql56.000002 |     4514 |              |                  |                   |
 +----------------+----------+--------------+------------------+-------------------+
 [root@mysql56 ~]#

//客户端连接mycat服务,读/写数据

[root@client50 ~]# mysql -h192.168.88.58 -P8066 -umycat -p654321

//查看表记录

mysql> select  * from testdb.user; 显示的是slave服务器user表的数据
 +-------+----------+
 | name  | password |
 +-------+----------+
 | yaya  | 123456   |
 | yayaA | 654321   |
 +-------+----------+
 2 rows in set (0.04 sec)

//插入表记录

mysql> insert into testdb.user values("yayaB","123456");

//在主服务器查看数据

[root@mysql56 ~]# mysql -e 'select * from testdb.user'
 +-------+----------+
 | name  | password |
 +-------+----------+
 | yaya  | 123456   |
 | yayaB | 123456   |
 +-------+----------+

//在主服务器查看日志偏移量

[root@mysql56 ~]# mysql -e 'show master status'
 +----------------+----------+--------------+------------------+-------------------+
 | File           | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
 +----------------+----------+--------------+------------------+-------------------+
 | mysql56.000002 |     4807 |              |                  |                   |
 +----------------+----------+--------------+------------------+-------------------+
 [root@mysql56 ~]#

//客户端连接mycat服务 可以查看到新存储的数据

[root@client50 ~]# mysql -h192.168.88.58 -P8066 -umycat -p654321 
 Mysql> select  * from testdb.user;
 +-------+----------+
 | name  | password |
 +-------+----------+
 | yaya  | 123456   |
 | yayaA | 654321   |
 | yayaB | 123456   |
 +-------+----------+
 Mysql>