利用MyCAT实现MySQL的读写分离

环境准备:

服务器共三台

所在主机的系统环境    CentOS Linux release 8.3.2011

mycat-server     10.0.0.10    #内存建议2G以上

mysql-master    10.0.0.20     mysql 8.0

mysql-slave       10.0.0.30    mysql 8.0

关闭selinux和firewalld,时间同步

systemctl stop firewalld

setenforce 0

ntpdate ntp.aliyun.com

1、创建MySQL主从数据库(详细步骤可以参考主从复制的那篇文章)

[root@mysql-master ~]# yum -y install mysql-server

[root@mysql-slave ~]# yum -y install mysql-server

#修改master和slave上的配置文件

[root@mysql-master ~]# vi /etc/my.cnf

[mysqld]

server-id=20

log-bin

[root@mysql-master ~]# systemctl enable --now mysqld

[root@mysql-slave ~]# vi /etc/my.cnf

[mysqld]

server-id=30

[root@mysql-slave ~]# systemctl enable --now mysqld

#master授权一个账号给从、可以从主复制数据

mysql> create user yzil@'%' identified by 'redhat';

mysql> grant replication slave on *.* to yzil@'%';

mysql> show master status;

mysql-master-bin.000001 |      659 |             

#slave使用有复制权限的用户账号连接至主服务器,并启动复制线程

mysql> CHANGE MASTER TO

    ->  MASTER_HOST='10.0.0.20',

    ->  MASTER_USER='yzil',

    ->  MASTER_PASSWORD='redhat',

    ->  MASTER_PORT=3306,

    ->  MASTER_LOG_FILE='mysql-master-bin.000001',

    ->  MASTER_LOG_POS=659;

mysql> start slave;

Query OK, 0 rows affected (0.00 sec)

mysql> show slave status\G

*************************** 1. row ***************************

              Slave_IO_State: Waiting for master to send event

                  Master_Host: 10.0.0.20

                  Master_User: yzil

                  Master_Port: 3306

                Connect_Retry: 60

              Master_Log_File: mysql-master-bin.000001

          Read_Master_Log_Pos: 659

              Relay_Log_File: mysql-slave-relay-bin.000002

                Relay_Log_Pos: 331

        Relay_Master_Log_File: mysql-master-bin.000001

            Slave_IO_Running: Yes

            Slave_SQL_Running: Yes

        Seconds_Behind_Master: 0

mysql>

2、在MySQL代理服务器10.0.0.10安装mycat并启动

[root@mycat-server ~]# yum -y install java

#确认安装成功

[root@mycat-server ~]# java -version

openjdk version "1.8.0_292"

OpenJDK Runtime Environment (build 1.8.0_292-b10)

OpenJDK 64-Bit Server VM (build 25.292-b10, mixed mode)

#下载并安装

[root@mycat-server ~]# wget http://dl.mycat.org.cn/1.6.7.6/20210303094759/Mycat-server-1.6.7.6-release-20210303094759-linux.tar.gz

[root@mycat-server ~]# mkdir /apps

[root@mycat-server ~]# tar xvf Mycat-server-1.6.7.6-release-20210303094759-linux.tar.gz -C /apps/

#配置环境变量

[root@mycat-server apps]# echo 'PATH=/apps/mycat/bin:$PATH' > /etc/profile.d/mycat.sh

[root@mycat-server apps]# source /etc/profile.d/mycat.sh

#查看端口

[root@mycat-server apps]# ss -ntl

State              Recv-Q            Send-Q                        Local Address:Port                        Peer Address:Port           

LISTEN            0                  128                                  0.0.0.0:22                                0.0.0.0:*               

LISTEN            0                  100                                127.0.0.1:25                                0.0.0.0:*               

LISTEN            0                  128                                    [::]:22                                  [::]:*               

LISTEN            0                  100                                    [::1]:25                                  [::]:*               

#启动mycat

[root@mycat-server ~]# cd /apps/mycat/bin/

[root@mycat-server bin]# mycat

Usage: /apps/mycat/bin/mycat { console | start | stop | restart | status | dump }

#注意:此步启动较慢,需要等一会儿,另外如果内存太小,会导致无法启动

[root@mycat-server bin]# mycat start

Starting Mycat-server...

#可以看到打开多个端口,其中8066端口用于连接mycat

[root@mycat-server bin]# ss -ntlp

State        Recv-Q      Send-Q            Local Address:Port              Peer Address:Port                                               

LISTEN      0            128                      0.0.0.0:22                    0.0.0.0:*          users:(("sshd",pid=971,fd=4))         

LISTEN      0            100                    127.0.0.1:25                    0.0.0.0:*          users:(("master",pid=1328,fd=16))     

LISTEN      0            1                      127.0.0.1:32000                  0.0.0.0:*          users:(("java",pid=26914,fd=4))       

LISTEN      0            50                            *:36691                        *:*          users:(("java",pid=26914,fd=74))       

LISTEN      0            128                        [::]:22                        [::]:*          users:(("sshd",pid=971,fd=6))         

LISTEN      0            100                        [::1]:25                        [::]:*          users:(("master",pid=1328,fd=17))     

LISTEN      0            50                            *:1984                        *:*          users:(("java",pid=26914,fd=73))       

LISTEN      0            128                            *:8066                        *:*          users:(("java",pid=26914,fd=103))     

LISTEN      0            50                            *:38819                        *:*          users:(("java",pid=26914,fd=72))       

LISTEN      0            128                            *:9066                        *:*          users:(("java",pid=26914,fd=99))       

[root@mycat-server bin]#

#查看日志,确定成功,可能需要一会才能看到成功的提示

[root@mycat-server ~]# tail /apps/mycat/logs/wrapper.log

STATUS | wrapper  | 2021/05/24 13:12:26 | --> Wrapper Started as Daemon

STATUS | wrapper  | 2021/05/24 13:12:26 | Launching a JVM...

INFO  | jvm 1    | 2021/05/24 13:12:27 | Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org

INFO  | jvm 1    | 2021/05/24 13:12:27 |  Copyright 1999-2006 Tanuki Software, Inc.  All Rights Reserved.

INFO  | jvm 1    | 2021/05/24 13:12:27 |

INFO  | jvm 1    | 2021/05/24 13:12:35 | MyCAT Server startup successfully. see logs in logs/mycat.log

[root@mycat-server ~]#

用默认密码123456来连接mycat

Centos8:无法连接mycat需要加参数连接

[root@mysql-slave ~]# mysql -uroot -p'123456' -h 10.0.0.10 -P8066

mysql: [Warning] Using a password on the command line interface can be insecure.

ERROR 1045 (HY000): Access denied for user 'root', because password is error 

[root@mysql-master ~]# vi /etc/my.cnf

[client]

default-auth=mysql_native_password

[root@mysql-master ~]# 

[root@mysql-master ~]# mysql -uroot -p'123456' -h 10.0.0.10 -P8066

mysql: [Warning] Using a password on the command line interface can be insecure.

Welcome to the MySQL monitor.  Commands end with ; or \g.

Your MySQL connection id is 11

Server version: 5.6.29-mycat-1.6.7.6-release-20210303094759 MyCat Server (OpenCloudDB)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its

affiliates. Other names may be trademarks of their respective

owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;

+----------+

| DATABASE |

+----------+

| TESTDB  |

+----------+

1 row in set (0.00 sec)

mysql>

3、定义mycat

mycat分前端和后端

前端,定义给前端APP连接

后端,定义转发至真实mysql server的规则

注意:前端APP连接数据库,只能连它自己的数据库,所以定义都是按库为单位进行定义的,不是整个mysql server

           后端真实库的权限问题,不要设置的太高

在mycat服务器上修改server.xml文件配置Mycat的连接信息,定义前端

[root@mycat-server ~]# vi /apps/mycat/conf/server.xml

                <!--

                        <property name="serverPort">8066</property>

                        <property name="managerPort">9066</property>

                        <property name="idleTimeout">300000</property>

                        <property name="authTimeout">15000</property>

                        <property name="bindIp">0.0.0.0</property>

                        <property name="dataNodeIdleCheckPeriod">300000</property> 5 * 60 * 1000L; //连接空闲检查

                        <property name="frontWriteQueueSize">4096</property> <property name="processors">32</property> -->

        <user name="root" defaultAccount="true">

                <property name="password">123456</property>

                <property name="schemas">TESTDB</property>

#改为下面

#修改8066改为3306,并取消注释信息

                        <property name="serverPort">3306</property>

                        <property name="managerPort">9066</property>

                        <property name="idleTimeout">300000</property>

                        <property name="authTimeout">15000</property>

                        <property name="bindIp">0.0.0.0</property>

                        <property name="dataNodeIdleCheckPeriod">300000</property>

                        <property name="frontWriteQueueSize">4096</property> <property name="processors">32</property>

或者:修改下面行的8066改为3306复制到独立非注释行

  <property name="serverPort">3306</property>

  <property name="handleDistributedTransactions">0</property>  #将上面行放在此行前面

        <user name="root" defaultAccount="true">              #连接mycat的用户名

                <property name="password">redhat</property>    #连接mycat的密码

                <property name="schemas">TESTDB</property>  #数据库名要和schema.xml相对应

#查看监听端口变为3306

[root@mycat-server bin]# ss -ntlp

State        Recv-Q      Send-Q            Local Address:Port              Peer Address:Port                                               

LISTEN      0            128                      0.0.0.0:22                    0.0.0.0:*          users:(("sshd",pid=971,fd=4))         

LISTEN      0            100                    127.0.0.1:25                    0.0.0.0:*          users:(("master",pid=1328,fd=16))     

LISTEN      0            1                      127.0.0.1:32000                  0.0.0.0:*          users:(("java",pid=27529,fd=4))       

LISTEN      0            128                        [::]:22                        [::]:*          users:(("sshd",pid=971,fd=6))         

LISTEN      0            50                            *:34327                        *:*          users:(("java",pid=27529,fd=72))       

LISTEN      0            100                        [::1]:25                        [::]:*          users:(("master",pid=1328,fd=17))     

LISTEN      0            50                            *:1984                        *:*          users:(("java",pid=27529,fd=73))       

LISTEN      0            50                            *:44771                        *:*          users:(("java",pid=27529,fd=74))       

LISTEN      0            128                            *:3306                        *:*          users:(("java",pid=27529,fd=103))     

LISTEN      0            128                            *:9066                        *:*          users:(("java",pid=27529,fd=99))       

[root@mycat-server bin]#

这里使用的是root,密码是redhat,逻辑数据库为TESTDB,可以定义多个TESTDB和TESTDB2,这些信息都可以自己随意定义,读写权限都有,没有针对表做任何特殊的权限。

4、修改schema.xml实现读写分离策略,定义后端

[root@mycat-server ~]# vi /apps/mycat/conf/schema.xml

<?xml version="1.0"?>

<!DOCTYPE mycat:schema SYSTEM "schema.dtd">

<mycat:schema xmlns:mycat="http://io.mycat/">

#定义schema,也就是后端虚拟库,并指定对应的虚拟节点

#当前端访问TESTDB这个虚拟库时,会转发到dn1这个节点

#建议虚拟库名和真实库名一致

        <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"> </schema>

#定义虚拟节点主机信息,及对应的真实库名称

#当前端访问请求到dn1,会转发到localhost1这个主机的db1库

#注意:db1指的是后端真实的库名

        <dataNode name="dn1" dataHost="localhost1" database="hellodb" />

#定义localhost1这个主机对应的真实后端,并指定路由规则

        <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"

                          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">

#心跳检测,检测后端真实server的可用性,使用select user()语句去检测

                <heartbeat>select user()</heartbeat>

#指定主要的写主机与读主机

#注意,账号密码,最好重新创建一个,尽量不要使用root

#注意,写,不能同时写,会有锁等待问题,一次写操作,只能在一个写节点进行写,读可以多个

                <writeHost host="host1" url="10.0.0.20:3306" user="root"

                                  password="123456">

                <readHost host="host1" url="10.0.0.30:3306" user="root"

                                  password="123456" />

                </writeHost>

#定义的虚拟节点对应的真实节点的路由规则

        </dataHost>

</mycat:schema>

#重新启动mycat

[root@mycat-server ~]# cd /apps/mycat/bin/

[root@mycat-server bin]# mycat restart

[root@mycat-server bin]# ss -ntlp

State        Recv-Q      Send-Q            Local Address:Port              Peer Address:Port                                               

LISTEN      0            128                      0.0.0.0:22                    0.0.0.0:*          users:(("sshd",pid=963,fd=4))         

LISTEN      0            100                    127.0.0.1:25                    0.0.0.0:*          users:(("master",pid=1460,fd=16))     

LISTEN      0            1                      127.0.0.1:32000                  0.0.0.0:*          users:(("java",pid=7156,fd=4))         

LISTEN      0            128                            *:3306                        *:*          users:(("java",pid=7156,fd=103))       

LISTEN      0            128                            *:9066                        *:*          users:(("java",pid=7156,fd=99))       

LISTEN      0            50                            *:38101                        *:*          users:(("java",pid=7156,fd=72))       

LISTEN      0            128                        [::]:22                        [::]:*          users:(("sshd",pid=963,fd=6))         

LISTEN      0            100                        [::1]:25                        [::]:*          users:(("master",pid=1460,fd=17))     

LISTEN      0            50                            *:40957                        *:*          users:(("java",pid=7156,fd=74))       

LISTEN      0            50                            *:1984                        *:*          users:(("java",pid=7156,fd=73))       

[root@mycat-server bin]#

balance属性

balance="0",不开启读写分离机制,所有读操作都发送到当前可用的writeHost上

balance="1",  定义的全部主机都参与select语句的负载均衡,也就是说,当双主双从模式下,M2,S1,S2都参与select语句的负载均衡

balance="2",  所有读请求随机的分发到writeHost,readHost上分布

balance="3",  所有读请求随机的分发到writeHost对应的readHost执行,writeHost不负担读压力,注意,balance=3,只有在1.4及以后的版本才有

writeType属性

writeType="0",所有写操作发送到配置的第一个writeHost,第一个挂了,切换到定义的第二个writeHost,这时,即使重启服务,也不会切换回去,还是以第二个writeHost为准

writeType="1", 所有写操作会随机发送到writeHost。注意,1.5版本以后废弃了,不推荐使用

上面配置中,balance改为1,表示读写分离,writeType="0",表示写操作发送到配置的第一个writeHost,第一个挂了,切换到定义的第二个writeHost

以上配置达到的效果就是10.0.0.20为主库,10.0.0.30为从库

注意:要保证能使用root/123456权限成功登录10.0.0.20和10.0.0.30机器上面的mysql数据库。同时也一定要授权mycat机器能使用root/123456权限成功登录这两台机器的mysql数据库!

5、在后端主服务器创建用户并对mycat授权

mysql> create database mycat;

mysql> create user root@'10.0.0.%' identified by '123456';

mysql> grant all on *.* to 'root'@'10.0.0.%';

mysql> fulsh privileges;

6、在mycat服务器上连接并测试

[root@mycat-server ~]# yum install -y mysql

[root@mycat-server ~]# vi /etc/my.cnf

[client]

default-auth=mysql_native_password

[root@mycat-server ~]# mysql -uroot -predhat -h 127.0.0.1 TESTDB

mysql> show databases;

+----------+

| DATABASE |

+----------+

| TESTDB  |          #只能看到一个虚拟数据库

+----------+

1 row in set (0.00 sec)

mysql> use TESTDB;

Database changed

mysql> create table t1(id int);

Query OK, 0 rows affected (0.31 sec)

mysql> select @@server_id;

+-------------+

| @@server_id |

+-------------+

|          30 |

+-------------+

1 row in set (0.02 sec)

mysql> select @@hostname;

+----------------------+

| @@hostname          |

+----------------------+

| mysql-slave.yzil.xyz |

+----------------------+

1 row in set (0.01 sec)

mysql>

7、通过通用日志确认实现读写分离

mysql> show variables like 'general_log';    #查看日志是否开启

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| general_log  | OFF  |

+---------------+-------+

1 row in set (0.01 sec)


mysql> set global general_log=on;              #开启日志功能

Query OK, 0 rows affected (0.00 sec)

mysql> show variables like 'general_log_file';    #查看日志文件保存位置

+------------------+--------------------------------+

| Variable_name    | Value                          |

+------------------+--------------------------------+

| general_log_file | /var/lib/mysql/mysql-slave.log |

+------------------+--------------------------------+

1 row in set (0.00 sec)

mysql>

在主和从服务器分别启用通用日志,查看读写分离

[root@mysql-master ~]# vi /etc/my.cnf

[mysqld]

general_log=ON

[root@mysql-master ~]# systemctl restart mysqld

mysql> show variables like 'general_log';

+---------------+-------+

| Variable_name | Value |

+---------------+-------+

| general_log  | ON    |

+---------------+-------+

1 row in set (0.13 sec)

mysql>

mysql> use TESTDB;

Database changed

mysql> show tables;

+-------------------+

| Tables_in_hellodb |

+-------------------+

| classes          |

| coc              |

| courses          |

| scores            |

| students          |

| t1                |

| teachers          |

| toc              |

+-------------------+

8 rows in set (0.01 sec)

mysql>

[root@mysql-master ~]# tail -f /var/lib/mysql/mysql-master.log

2021-05-25T03:05:00.603842Z   11 Query select user()  #mycat对后端服务器的健康性检查方法select user()

2021-05-25T03:05:10.603841Z   13 Query select user() 

2021-05-25T03:05:20.603842Z     8 Query select user()

[root@mysql-slave ~]# tail -f /var/lib/mysql/mysql-slave.log

2021-05-25T03:05:10.603257Z   13 Query select user()

2021-05-25T03:05:11.616535Z   12 Query show tables

2021-05-25T03:05:20.603478Z   14 Query select user()

#从日志中可以观察到读是在slave上面

8、停止从节点,mycat自动调度读请求至主节点

     停止主节点,mycat不会自动调度写请求至从节点

[root@mysql-slave ~]# systemctl stop mysqld

[root@mycat-server ~]# mysql -uroot -predhat -h 127.0.0.1 TESTDB

mysql> select @@server_id;

+-------------+

| @@server_id |

+-------------+

|          20 |

+-------------+

1 row in set (0.01 sec)

mysql>

#停止主节点,mycat不会自动调度写请求至从节点

mysql> insert teachers values (5,'yyy','M');

ERROR 1184 (HY000): java.net.ConnectException: Connection refused

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容