likes
comments
collection
share

mycat读写分离详解

作者站长头像
站长
· 阅读数 48

MyCat的主要功能和特点

  1. 读写分离:MyCat可以配合数据库的主从模式实现读写分离,即主数据库(master)处理事务性增、改、删操作(INSERT、UPDATE、DELETE),而从数据库(slave)处理SELECT查询操作,以提高数据库的整体性能和查询速度。
  2. 分库分表:MyCat支持分库分表,通过某种特定的条件,将存放在同一个数据库中的数据分散存放在多个数据库(主机)中,以达到分散单台设备负载的效果。这包括垂直切分(按照业务将表进行分类,分布到不同的数据库上面)和水平切分(一个表格的数据按照行分割到多个节点上)。
  3. 多数据源支持:MyCat不仅支持MySQL,还支持Oracle、MSSQL、PG、DB2等主流关系型数据库,以及MongoDB等非关系型数据库。这意味着前端应用可以只与MyCat交互,而不需要直接与各种不同类型的数据库打交道。
  4. 高性能和可扩展性:MyCat通过连接池复用机制、SQL拦截和分片解析等技术,提高了数据库的并发访问能力和查询性能。同时,MyCat支持动态扩展,可以根据业务需求灵活增加或减少数据库节点。

MyCat的架构和原理

MyCat的架构主要包括前端代理层、路由层、数据节点层等部分。当用户发送SQL语句到MyCat时,MyCat会首先拦截这个SQL语句,并进行一系列的分析处理(如分片分析、路由分析、读写分离分析等),然后将处理后的SQL语句发送到后端的真实数据库节点去执行,并将返回的结果进行适当的处理后再返回给用户。

MyCat的核心原理是“拦截”和“分片”。它拦截了用户发送过来的SQL语句,并根据预设的分片规则将SQL语句分发到不同的数据节点去执行。分片规则可以根据表的某个字段的某种规则来定义,如哈希算法、取模算法等。

MyCat的应用场景

MyCat适用于以下应用场景:

  • 高并发、大数据量的Web应用:如电商网站、社交媒体等,这些应用需要处理大量的用户请求和数据存储。
  • 分布式系统:在分布式系统中,数据往往分布在多个节点上,MyCat可以作为数据访问的中间层,实现数据的透明访问和负载均衡。
  • 读写分离和数据库备份:通过MyCat可以实现数据库的读写分离和主从备份,提高数据库的可靠性和性能。
  • 多租户应用:每个租户可以拥有自己独立的数据库实例,但前端应用只需要与MyCat交互即可实现多租户的数据隔离和共享。

MyCat的优缺点

优点

  • 支持多种数据库:MyCat支持多种主流数据库和非关系型数据库,方便前端应用与多种数据库交互。
  • 高性能和可扩展性:通过连接池复用、SQL拦截和分片解析等技术,MyCat提高了数据库的并发访问能力和查询性能,并支持动态扩展。
  • 读写分离和主从备份:MyCat可以实现数据库的读写分离和主从备份,提高数据库的可靠性和性能。

缺点

  • 分布式事务处理困难:在分布式系统中,跨多个数据库节点的事务处理变得复杂和困难。
  • 跨节点JOIN操作复杂:在分库分表的情况下,跨多个数据库节点的JOIN操作需要额外的处理逻辑和性能开销。

mycat部署

mycat安装目录结构说明
  • bin :mycat命令,启动、重启、停止等运行目录
  • catlet: catlet为Mycat的一个扩展功能
  • conf :mycat 配置信息,重点关注
  • lib:mycat引用的jar包,Mycat是java开发的
  • logs日志文件,包括Mycat启动的日志和运行的日志
  • version.txt :mycat版本说明
Mycat的常用配置文件

Mycat的配置文件都在conf目录里面,这里介绍几个常用的文件:

  • server.xml :Mycat软件本身相关的配置文件,设置账号、参数等
  • schema.xml:Mycat对应的物理数据库和数据库表的配置,读写分离、高可用、分布式策略定制、节点控制
  • rule.xml:Mycat分片(分库分表)规则配置文件,记录分片规则列表、使用方法等
Mycat日志

Mycat的日志文件都在logs目录里面

  • wrapper.log :mycat启动日志
  • mycat.log :mycat详细工作日志
mycat 实现读写分离
1.环境准备

mycat服务器上不能装mysql

master服务器192.168.10.1
slave1服务器192.168.10.10
mycat服务器192.168.10.20
客户机192.168.10.30
2.初始化环境
每台服务器上都初始化,关闭防火墙
systemctl stop --now firewalld
systemctl disable firewalld
setenforce 0
3部署主从复制
###################### 主mysql服务器配置(192.168.10.10)########################
[root@localhost ~]#vim  /etc/my.cnf
#修改文件
[mysqld]
server_id=100
log-bin=/data/mysql/mysql-bin
general_log 
[root@localhost ~]#mkdir /data/mysql/   -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld

select @@server_id;
#可以查看serverid  默认都是1
show master status;
#查看二进制日志位置

grant replication slave on *.* to test@'192.168.10.%' identified by 'Admin@123';



#建立复制用户

show processlist;
#查看线程


############################# 从mysql服务器配置(192.168.10.20)################
[root@localhost ~]#vim  /etc/my.cnf
#修改文件
[mysqld]
server_id=101
log-bin=/data/mysql/mysql-bin
relay-log=relay-log-bin
relay-log-index=slave-relay-bin.index
general_log

#read only  #只读可加


[root@localhost ~]#mkdir /data/mysql/   -p
#建立文件夹
[root@localhost ~]#chown mysql.mysql /data/ -R
#注意修改权限
[root@localhost ~]#systemctl restart mysqld



下面修改配置 命令较长可以使用帮助
help change master to


CHANGE MASTER TO
  MASTER_HOST='192.168.10.10',
  MASTER_USER='test',
  MASTER_PASSWORD='Admin@123',
  MASTER_PORT=3306,
  MASTER_LOG_FILE='mysql-bin.000003',
  MASTER_LOG_POS=154;
  注意最后分号


show slave status\G;
#查看设置的状态
Seconds_Behind_Master: NULL    #目前数据差

start slave;
#开启线程,开启主从复制

create database cxk;
#在主节点上建立数据测试


####################### 在master服务器上上传库文件,并在从服务器上验证主从同步 ############

#在主服务器上下载hellodb库文件,source后加绝对路径
[root@localhost ~]#mysql -uroot -pAdmin@123
#下载hellodb库文件
source /bak/hellodb.sql
show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| hellodb            |
| mysql              |
| performance_schema |
| sys                |
+--------------------+

#在从库中查看库文件hellodb是否已经同步
show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| hellodb            |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
4.安装mycat(192.168.10.1)
1)主机上安装java(mycat基于java)
#yum安装java
[root@localhost ~]#yum install java -y
#确认安装成功
[root@localhost ~]#java -version
openjdk version "1.8.0_131"
OpenJDK Runtime Environment (build 1.8.0_131-b12)
OpenJDK 64-Bit Server VM (build 25.131-b12, mixed mode)

2)切换至opt目录,下载mycat安装包
[root@localhost ~]#cd /opt
[root@localhost ~]#wget http://dl.mycat.org.cn/1.6.7.6/20210303094759/Mycat-server-1.6.7.6-release-20210303094759-linux.tar.gz

3)创建/apps文件夹,并解压mycat包至/apps下
[root@localhost ~]#mkdir /apps
[root@localhost ~]#tar zxvf Mycat-server-1.6.7.6-release-20210303094759-linux.tar.gz -C /apps/

4)设置变量环境
[root@localhost ~]#echo 'PATH=/apps/mycat/bin:$PATH' > /etc/profile.d/mycat.sh
[root@localhost ~]#source /etc/profile.d/mycat.sh

5)启动mycat,查看日志文件,最后可以看到启动成功
[root@localhost ~]#mycat start
#注意内存小于2G 起不来
Starting Mycat-server...

[root@localhost ~]#tail -f /apps/mycat/logs/wrapper.log
#启动成功日志末尾会出现successfully
STATUS | wrapper  | 2021/12/09 21:04:10 | --> Wrapper Started as Daemon
STATUS | wrapper  | 2021/12/09 21:04:10 | Launching a JVM...
INFO   | jvm 1    | 2021/12/09 21:04:11 | Wrapper (Version 3.2.3) http://wrapper.tanukisoftware.org
INFO   | jvm 1    | 2021/12/09 21:04:11 |   Copyright 1999-2006 Tanuki Software, Inc.  All Rights Reserved.
INFO   | jvm 1    | 2021/12/09 21:04:11 | 
INFO   | jvm 1    | 2021/12/09 21:04:12 | MyCAT Server startup successfully. see logs in logs/mycat.log


(6)客户端连接数据库
#这里密码初始为123456   需要加端口
[root@localhost bin]#mysql -uroot -p123456 -h 192.168.10.1 -P8066
5.修改 mycat 配置文件 /apps/mycat/conf/server.xml
[root@localhost ~]#vim /apps/mycat/conf/server.xml

#去掉44行行注释,对应的在51行行末注释,删除50行行末注释,5 * 60 * 1000L; //连接空>    闲检查

#修改45行端口号为3306
45 <property name="serverPort">3306</property>

#配置Mycat的连接信息(账号密码),在110 和111行, 可以修改,这边不修改了
####参数解释说明####
110         <user name="root" defaultAccount="true">
111                 <property name="password">123456</property>
112                 <property name="schemas">TESTDB</property>
113                 <property name="defaultSchema">TESTDB</property>

116                 <!-- 表级 DML 权限设置 -->
117                 <!-- 
118                 <privileges check="false">
119                         <schema name="TESTDB" dml="0110" >
120                                 <table name="tb01" dml="0000"></table>
121                                 <table name="tb02" dml="1111"></table>
122                         </schema>
123                 </privileges>   
124                  -->

127         <user name="user">
128                 <property name="password">user</property>
129                 <property name="schemas">TESTDB</property>
130                 <property name="readOnly">true</property>
131                 <property name="defaultSchema">TESTDB</property>

user    用户配置节点
name    逻辑用户名,客户端登录MyCAT的用户名,也就是客户端用来连接Mycat的用户名。
password     客户端登录MyCAT的密码
schemas      数据库名,这里会和schema.xml中的配置关联,可配置多个,多个用逗号分开,例如:db1,db2
privileges   配置用户针对表的增删改查的权限
readOnly mycat   逻辑库所具有的权限。true为只读,false为读写都有,默认为false

##注意
1.#server.xml文件里登录mycat的用户名和密码可以任意定义,这个账号和密码是为客户机登录mycat时使用的账号信息
2.#逻辑库名(如上面的TESTDB,也就是登录mycat后显示的库名,切换这个库之后,显示的就是代理的真实mysql数据库的表)要在schema.xml里面也定义,否则会导致mycat服务启动失败!这里只定义了一个标签,所以把多余的都注释了。如果定义多个标签,即设置多个连接mycat的用户名和密码,那么就需要在schema.xml文件中定义多个对应的库!
6.修改 mycat 配置文件/apps/mycat/conf/schema.xml

schema.xml是最主要的配置项,此文件关联mysql读写分离策略,读写分离、分库分表策略、分片节点都是在此文件中配置的.MyCat作为中间件,它只是一个代理,本身并不进行数据存储,需要连接后端的MySQL物理服务器,此文件就是用来连接MySQL服务器的。

[root@localhost ~]#vim  /apps/mycat/conf/schema.xml
#删除所有内容,重新写入以下
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
        <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1">
        #schema标签:数据库设置,此数据库为逻辑数据库,name与server.xml中schema对应。
        #name:逻辑数据库名,与server.xml中的schema对应;
        #checkSQLschema: 数据库前缀相关设置,这里为false;
        #sqlMaxLimit:  select时默认的limit,避免查询全表,否则可能会遇到查询量特别大的情况造成卡 死;
        #dataNode:表存储到哪些节点,多个节点用逗号分隔。节点为下文dataNode设置的name
</schema>
        <dataNode name="dn1" dataHost="localhost1" database="hellodb" />
        #dataNode标签: 定义mycat中的数据节点,也是通常说的数据分片,也就是分库相关配置
        #name: 定义数据节点的名字,与table中dataNode对应
        #datahost: 物理数据库名,与datahost中name对应,该属性用于定义该分片属于哪个数据库实例
        #database: 物理数据库中数据库名,该属性用于定义该分片属性哪个具体数据库实例上的具体库
        <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
        #dataHost标签: 物理数据库,真正存储数据的数据库
        #name: 物理数据库名,与dataNode中dataHost对应
        #maxCon属性指定每个读写实例连接池的最大连接。也就是说,标签内嵌套的writeHost、readHost标  签都会使用这个属性的值来实例化出连接池的最大连接数
        #minCon属性指定每个读写实例连接池的最小连接,初始化连接池的大小
        #balance: 均衡负载的方式
       
                  writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                  #writeType: 写入方式
                  #dbType: 数据库类型
                  #dbDriver指定连接后端数据库使用的 Driver,目前可选的值有 native 和 JDBC。用 native 的话,因为这个值执行的是二进制的 mysql 协议,所以可以使用 mysql 和maridb。其他类型的数据库则需要使用 JDBC 驱动来支持。
                  #switchType:  “-1” 表示不自动切换; “1” 默认值,自动切换; “2” 基于 MySQL主从同步的状态决定是否切换心跳语句为 show slave status; “3” 基于 MySQL galary cluster 的切换机制(适合集群)(1.4.1)心跳语句为 show status like ‘wsrep%’.
                <heartbeat>select user()</heartbeat>
                #heartbeat: 心跳检测语句,注意语句结尾的分号要加
                <writeHost host="host1" url="192.168.59.113:3306" user="root" password="123456">
                #host:用于标识不同实例,一般 writeHost 我们使用*M1,readHost 我们用*S1。
                #url:后端实例连接地址。Native:地址:端口 JDBC:jdbc的url
                #user:后端存储实例需要的用户名字
                #password:后端存储实例需要的密码
                 <readHost host="host2" url="192.168.59.112:3306" user="root" password="123456"/>

                </writeHost>
        </dataHost>
</mycat:schema>


#schema.xml文件中有三点需要注意:balance="1",writeType="0" ,switchType="1" 
#schema.xml中的balance的取值决定了负载均衡对非事务内的读操作的处理。balance 属性负载均衡类型,目前的取值有 4 种:
##balance="0":不开启读写分离机制,所有读操作都发送到当前可用的writeHost上,即读请求仅            发送到writeHost上
##balance="1":一般用此模式,读请求随机分发到当前writeHost对应的readHost和standby的writeHost上。即全部的readHost与stand by writeHost 参与 select 语句的负载均衡,简单的说,当双主双从模式(M1 ->S1 , M2->S2,并且 M1 与 M2 互为主备),正常情况下, M2,S1, S2 都参与 select 语句的负载均衡
##balance="2":读请求随机分发到当前dataHost内所有的writeHost和readHost上。即所有读操作都随机的在writeHost、 readhost 上分发
##balance="3":读请求随机分发到当前writeHost对应的readHost上。即所有读请求随机的分发wiriterHost 对应的 readhost 执行, writerHost 不负担读压力,注意 balance=3 只在 1.4 及其以后版本有,1.3 没有

###writeHost和readHost标签,这两个标签都指定后端数据库的相关配置给mycat,用于实例化后端连接池。唯一不同的是:writeHost指定写实例、readHost指定读实例,组着这些读写实例来满足系统的要求。在一个dataHost内可以定义多个writeHost和eadHost。但是,如果writeHost指定的后端数据库宕机,那么这个writeHost绑定的所有readHost都将不可用。另一方面,由于这个writeHost宕机系统会自动的检测到,并切换到备用的writeHost上去   
               
#PS:Mycat主从分离只是在读的时候做了处理,写入数据的时候,只会写入到writehost,需要通过mycat的主从复制将数据复制到readhost
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
        <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"></schema>
        <dataNode name="dn1" dataHost="localhost1" database="hellodb" />
        <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
                  writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <writeHost host="host1" url="192.168.10.10:3306" user="root" password="Admin@123">
                 <readHost host="host2" url="192.168.10.20:3306" user="root" password="Admin@123"/>
                </writeHost>
        </dataHost>
</mycat:schema>
7. 主从服务器上授权
[root@localhost ~]#mysql -uroot -p123123
#授权
GRANT ALL ON *.* TO 'root'@'192.168.10.%' IDENTIFIED BY 'Admin@123';

#查看创建成功
use mysql;
select user,host from user;

从也要创建用户

8.重启mycat服务,客户机连接mycat
1)在mycat服务器上,重启mycat服务,查看启动日志,文末出现successfully
 [root@localhost ~]#mycat restart  
 [root@localhost ~]#tail -f /apps/mycat/logs/wrapper.log


(2)查看3306端口,可以监听到主从服务器
 [root@localhost ~]# ss -antp|grep 3306


 
3)在客户机上登录mycat,这时可以不加端口直接进入数据库了
[root@localhost ~]#mysql -uroot -p123456 -h192.168.10.1
#看是否能查到表   
create table student (id smallint unsigned primary key auto_increment, name varchar(10), age tinyint unsigned,gender enum('M','F') default 'M' );
show databases;
use TESTDB;
show tables;
+-------------------+
| Tables_in_hellodb |
+-------------------+
| classes           |
| coc               |
| courses           |
| scores            |
| students          |
| teachers          |
| toc               |
+-------------------+

#查看当前的查询来自哪台服务器,可以看到查询功能来自id为2的从服务器
select @@server_id;
+-------------+
| @@server_id |
+-------------+
|           2 |
+-------------+

9.客户端测试读写分离
1)在主从服务器上都打开通用日志
[root@localhost ~]#mysql -uroot -p123123
#打开通用日志
set global general_log=1;
#查看通用查询日志是否开启
show variables like 'general%';
+------------------+-------------------------------------+
| Variable_name    | Value                               |
+------------------+-------------------------------------+
| general_log      | ON                                  |
| general_log_file | /usr/local/mysql/data/localhost.log |
+------------------+-------------------------------------+

set global general_log=1;
show variables like 'general%';

2)在主从服务器上实时查看通用日志
[root@localhost ~]#tail -f /usr/local/mysql/data/localhost.log

3)在客户机上的表中插入数据,并查看主从服务器实时日志,可以看到只有主服务器上有日志变化显示
[root@localhost ~]#mysql -uroot -p123456 -h 192.168.59.114
insert into teachers values(5,'Xiao Ming',46,'F');

4)在客户机上select查表,并查看主从服务器实时日志,可以看到只有从服务器上有日志变化显示,从而实现了读写分离
select * from teachers;
转载自:https://juejin.cn/post/7389077092136304692
评论
请登录