当前位置:   article > 正文

分库分表中间件-Mycat

分库分表中间件-Mycat

MyCat笔记
一、MyCat简介
Mycat 是一个开源的分布式数据库系统,但是由于真正的数据库需要存储引擎,而 Mycat 并没有存储引擎,所以并不是完全意义的分布式数据库系统。mycat只能作为一个数据库中间件,用于在数据库集群中实现分表、读写分离、主从复制。以下通过两张图简单的介绍一下mycat的工作方式。
在以往的应用中,应用程序直接与数据库进行连接,将命令发送给数据库,由数据库进行处理并响应结果。

如果使用mycat作为数据库中间件,在mycat中可以进行主从、分表等等的配置,那么应用程序将不再与数据库进行直接的连接,而是与mycat进行连接,将命令发送给mycat,最后由mycat根据配置中的算法来决定将命令交给哪一个数据库来执行,数据库执行命令之后数据返回给mycat,最后mycat在将数据返回给应用程序。

二、MyCat的安装和配置
准备工作,我们要使用MyCat来实现分表、读写分离、主从复制都需要涉及到多个mysql服务,所以首先在我们的计算机上安装4个mysql服务(使用压缩版进行安装)。
为了演示mycat作为数据库中间件对数据库进行分片,我们在当前的计算机上需要同时安装4个mysql服务,分别是mysql1、mysql2、mysql3、mysql4,占用的端口为13306、13307、13308、13309。同时,mysql1为主库,mysql2为mysql1的从库,mysql3为主库,mysql4为mysql3的从库。
主库安装过程如下:
由于我们需要安装多个mysql服务,所以最好使用mysql官网提供的压缩版进行安装。
1.安装mysql1服务作为主数据库
将下载好的安装包解压到任意目录,为了便于查找推荐大家将所有的mysql文件夹都存放到同一个目录中。
2.打开mysql文件夹中mysql-default.ini文件,需要配置端口信息,mysql目录信息,以及主数据库配置。

#新增主库配置 server_id不能重复
server_id=1
log_bin=master-bin
log_bin-index=master-bin.index
#修改原有的默认配置
basedir =D:\work\mysql\mysql1\mysql-5.6.46-winx64
datadir =D:\work\mysql\mysql1\mysql-5.6.46-winx64\data
port =13306
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

3.配置文件修改完毕以后,在bin目录下打开控制台执行命令安装服务。
压缩版安装命令:注意引号为英文输入法下的引号
mysqld --install 服务名称 --defaults-file=’‘D:\work\mysql\mysql1\mysql-5.6.46-winx64\my-default.ini’’
从库安装过程如下:
从库的安装过程和主库类似,区别在于从库的配置文件中需要提供的是从库的配置。

#新增从库配置
server_id=2
relay-log-index=slave-relay-bin.index
relay-log=slave-relay-bin
  • 1
  • 2
  • 3
  • 4

在这一步要注意,如果你的mysql文件夹是复制的,那么随机生成的服务ID是相同的,在mysql\data\auto.cnf文件中能查看到服务的id,如果相同那个就将这个文件重命名为mysql\data\auto.cnf.bak等待mysql重新生成一个。

4.两个服务都安装完成以后,需要进行主从关联。
首先在给主数据库的一个用户授予从库访问主库的权限(从库需要使用这个账户连接主库,并读取日志文件,以便于进行主从复制)。
此处以root用户为例:

grant replication slave on *.* to 'root'@'localhost' identified by '';
flush privileges;
  • 1
  • 2

5.然后在从库中通过命令与主库进行关联
首先通过show master status\G;命令查看主数据库状态,包括了主数据库的日志文件名称,日志文件的位置。
例如:

上图中的file就是主数据库日志文件的名称,position就是日志文件的位置。这两个数据在首次进行主从关联时需要使用。
在从库执行命令:

change master to master_host='localhost',master_port=13306,master_user='root',master_password='',master_log_file='master-bin.000003',master_log_pos=557;
start slave;
  • 1
  • 2

注意:一旦建立主从关系,主数据库的任何增删改操作都会记录到日志中,从库通过读取日志文件会执行相同的操作,所以一定要保证主库有的数据库、表在从库中也要有。
MyCat运行环境要求:jdk1.7+、mysql5.5+
1.下载MyCat
官网下载地址http://www.mycat.org.cn/
GIT下载地址https://github.com/MyCATApache/Mycat-download
2.解压
3.修改配置文件
默认情况下mycat会占用4G的虚拟机内存,但是java虚拟机内存一般不会设置这么大,所以需要修改配置文件来修改默认占用的内存大小。
打开mycat目录中的conf中的wrapper.conf文件
修改java执行程序地址:
wrapper.java.command=C:\Program Files\java\JDK1.8u74_x86\bin\java.exe
将36行和37行替换为:
wrapper.java.additional.10=-Xmx512M
wrapper.java.additional.11=-Xms64M
4.安装服务
在mycat的bin目录中打开控制台,输入mycat.bat install命令安装服务,服务安装完成之后,启动服务依然要在bin目录中,通过mycat.bat start命令启动服务。如果要停止服务则执行mycat.bat stop命令。
三、MyCat重要概念
MyCat的一项重要功能就是进行分库分表,按照分表的方式不同又可以分为垂直拆分和水平拆分。
垂直拆分:
一个数据库由很多表的构成,每个表对应着不同的业务,垂直切分是指按照业务将表进行分类,分布到不同的数据库上面,这样也就将数据或者说压力分担到不同的库上面。
优点:
• 拆分后业务清晰,拆分规则明确;
• 系统之间整合或扩展容易;
• 数据维护简单。
缺点:
• 部分业务表无法 join,只能通过接口方式解决,提高了系统复杂度;
• 受每种业务不同的限制存在单库性能瓶颈,不易数据扩展跟性能提高;
• 事务处理复杂。
由于垂直切分是按照业务的分类将表分散到不同的库,所以有些业务表会过于庞大,存在单库读写与存储瓶颈,所以就需要水平拆分来做解决。
水平拆分:
相对于垂直拆分,水平拆分不是将表做分类,而是按照某个字段的某种规则来分散到多个库之中,每个表中包含一部分数据。简单来说,我们可以将数据的水平切分理解为是按照数据行的切分,就是将表中的某些行切分到一个数据库,而另外的某些行又切分到其他的数据库中。
几种典型的分片规则包括:
• 按照用户 ID 求模,将数据分散到不同的数据库,具有相同数据用户的数据都被分散到一个库中;
• 按照日期,将不同月甚至日的数据分散到不同的库中;
• 按照某个特定的字段求摸,或者根据特定范围段分散到不同的库中
优点:
• 拆分规则抽象好,join 操作基本可以数据库做;
• 不存在单库大数据,高并发的性能瓶颈;
• 应用端改造较少;
• 提高了系统的稳定性跟负载能力。

缺点:
• 拆分规则难以抽象;
• 分片事务一致性难以解决;
• 数据多次扩展难度跟维护量极大;
• 跨库 join 性能较差

重要概念:
逻辑库(Schema)
在前面mycat的介绍中我们说了mycat是一个数据库中间件,应用程序将会直接与mycat连接,对于mycat身后的数据库集群是不了解的。
也就是说应用程序会将mycat作为数据库来看待,业务开发人员只需要知道数据库的概念,所以数据库中间件可以被看做是一个或多个数据库集群构成的逻辑库。逻辑库将会与真正的数据库进行映射。
逻辑表(Table)
既然有逻辑库,那么就会有逻辑表,分布式数据库中,对应用来说,读写数据的表就是逻辑表。逻辑表可以映射真实数据库中的一张表或者多张表。
分片节点(dataNode)
数据切分后,一个大表被分到不同的分片数据库上面,每个表分片所在的真实数据库就是分片节点(dataNode)。
节点主机(dataHost)
数据切分后,每个分片节点(dataNode)不一定都会独占一台机器,同一机器上面可以有多个分片数据库,这样一个或多个分片节点(dataNode)所在的机器就是节点主机(dataHost)。
分片规则(rule)
前面讲了数据切分,一个大表被分成若干个分片表,就需要一定的规则,这样按照某种业务规则把数据分到某个分片的规则就是分片规则。
全局序列号(sequence)
数据切分后,原有的关系数据库中的主键约束在分布式条件下将无法使用,因此需要引入外部机制保证数据唯一性标识,这种保证全局性的数据唯一标识的机制就是全局序列号(sequence)。
全局表
一个真实的业务系统中,往往存在大量的类似字典表的表,这些表基本上很少变动,字典表具有以下几个特性:
• 变动不频繁;
• 数据量总体变化不大;
• 数据规模不大,很少有超过数十万条记录。
对于这类的表,在分片的情况下,当业务表因为规模而进行分片以后,业务表与这些附属的字典表之间的关联,就成了比较棘手的问题,所以 Mycat 中通过数据冗余来解决这类表的 join,即所有的分片都有一份数据的拷贝,所有将字典表或者符合字典表特性的一些表定义为全局表。数据冗余是解决跨分片数据 join 的一种很好的思路,也是数据切分规划的另外一条重要规则。
ER 表
关系型数据库是基于实体关系模型(Entity-Relationship Model)之上,通过其描述了真实世界中事物与关系,mycat 中的 ER 表即是来源于此。根据这一思路,提出了基于 E-R 关系的数据分片策略,子表的记录与所关联的父表记录存放在同一个数据分片上,即子表依赖于父表,通过表分组(Table Group)保证数据 Join 不会跨库操作。表分组(Table Group)是解决跨分片数据 join 的一种很好的思路,也是数据切分规划的重要一条规则。
数据库分片原则:
原则一:能不分就不分,1000 万以内的表,不建议分片,通过合适的索引,读写分离等方式,可以很好的解决性能问题。
原则二:分片数量尽量少,分片尽量均匀分布在多个 DataHost 上,因为一个查询 SQL 跨分片越多,则总体性能越差,虽然要好于所有数据在一个分片的结果,只在必要的时候进行扩容,增加分片数量。
原则三:分片规则需要慎重选择,分片规则的选择,需要考虑数据的增长模式,数据的访问模式,分片关联性问题,以及分片扩容问题,最近的分片策略为范围分片、枚举分片、一致性 Hash分片,这几种分片都有利于扩容。
原则四:尽量不要在一个事务中的 SQL 跨越多个分片,分布式事务一直是个不好处理的问题。
原则五:查询条件尽量优化,尽量避免 Select * 的方式,大量数据结果集下,会消耗大量带宽和 CPU 资源,查询尽量避免返回大量结果集,并且尽量为频繁使用的查询语句建立索引。

四、MyCat配置
mycat的conf目录中有三个比较重要的xml文件,server.xml、schema.xml、rule.xml。
server.xml 用于配置mycat的用户信息以及用户对于逻辑库的访问权限。
schema.xml 用于配置mycat的逻辑库、节点、主机等信息。
rule.xml 用于配置数据库的分片规则
1.server.xml的配置

privileges标签:可以配置更为详细的权限控制。

<privileges check="false">
	<schema name="TESTDB" dml="0110" >
		<table name="tb01" dml="0000"></table>
		<table name="tb02" dml="1111"></table>
	</schema>
</privileges>	
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

上述标签中check属性设置为true表示要开启权限检查。schema用于配置逻辑库的详细权限配置,name属性表示逻辑库名称,table用于配置逻辑表的详细权限配置。dml为权限规则,权限规则由4位的数字组成,每一位只能填0或者1,从左到右分别表示insert,update,select,delete。设置为1表示拥有该权限,设置为0表示不具备该权限。
注意schema中的dml是全局权限,默认情况下该逻辑库中的所以逻辑表都遵照该权限设置,如果单独使用table进行了权限配置,那么则遵照table的权限配置而定。
system标签:用于对mycat进行系统设置,以下列出一些常见的配置
utf8
字符集

1
处理线程数量,默认是cpu数量。

4096
每次读取保留的数量,默认4096。

100
全局ID生成方式。(0:为本地文件方式,1:为数据库方式;2:为时间戳序列方式;3:为ZK生成ID;4:为ZK递增ID生成。

1800000
指定连接的空闲超时时间。某连接在发起空闲检查下,发现距离上次使用超过了空闲时间,那么这个连接会被回收,就是被直接的关闭掉。默认 30 分钟,单位毫秒。

300
SQL 执行超时的时间,Mycat 会检查连接上最后一次执行 SQL 的时间,若超过这个时间则会直接关闭这连接。默认时间为 300 秒,单位秒。

10000
对后端所有读、写库发起心跳的间隔时间,默认是 10 秒,单位毫秒。

0.0.0.0
mycat 服务监听的 IP 地址,默认值为 0.0.0.0。

8066
定义 mycat 的使用端口,默认值为 8066。

9066
定义 mycat 的管理端口,默认值为 9066。

5.6
mycat 模拟的 mysql 版本号,默认值为 5.6 版本,如非特需,不要修改这个值,目前支持设置 5.5,5.6,5.7 版本,其他版本可能会有问题。

2、schema.xml的配置
schema.xml文件是mycat中非常重要的文件,所有的数据库节点、数据库主机、逻辑库、主从、都需要在该配置文件中进行配置。
在详细说明schema.xml的配置文件之前,首先回顾一下本地的环境以便于大家理解。当前计算机上安装了4个mysql服务,分别是mysql1:13306、mysql2:13307、mysql3:13308、mysql4:13309。本次使用mycat的最终目的是mysql1为主1,mysql2为从1,mysql3为主2,mysql4为从2。两套主从数据库分别作为mycat的分片节点。
schema.xml主要进行三方面的配置,而这三方面的配置是缺一不可的。
schema 数据库设置,此数据库为逻辑数据库,name与server.xml中schema对应
dataNode 分片信息,也就是分库相关配置
dataHost 物理数据库主机地址

schema 标签

schema标签用来定义mycat实例中的逻辑库,mycat可以有多个逻辑库,每个逻辑库都有自己的相关配置。可以使用schema标签来划分这些不同的逻辑库
如果不配置schema标签,所有表的配置会属于同一个默认的逻辑库。逻辑库的概念和MySql的database的概念一样,我们在查询两个不同逻辑库中的表的时候,需要切换到该逻辑库下进行查询。
name 逻辑数据库名,与server.xml中的schema对应
checkSQLschema 数据库前缀相关设置,当该值为true时,例如我们执行语句select * from TESTDB.company 。mycat会把语句修改为 select * from company 去掉TESTDB。
sqlMaxLimit 当该值设置为某个数值时,每条执行的sql语句,如果没有加上limit语句,Mycat会自动加上对应的值。不写的话,默认返回所有的值。
需要注意的是,如果运行的schema为非拆分库的,那么该属性不会生效。需要自己sql语句加limit。
table 标签

<table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />
<table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
  • 1
  • 2

name 表名,物理数据库中表名
dataNode 表存储到哪些节点,多个节点用逗号分隔。节点为下文dataNode设置的name
primaryKey 主键字段名,自动生成主键时需要设置
autoIncrement 是否自增
rule 分片规则名,具体规则下文rule详细介绍
type 该属性定义了逻辑表的类型,目前逻辑表只有全局表和普通表。全局表: global 普通表:无

childTable标签

<table name="customer" primaryKey="ID" dataNode="dn1,dn2" rule="sharding-by-intfile"> 
<childTable name="c_a" primaryKey="ID" joinKey="customer_id" parentKey="id" />
</table>
  • 1
  • 2
  • 3

childTable 标签用于定义 E-R 分片的子表。通过标签上的属性与父表进行关联。
name 子表的名称
joinKey 子表中字段的名称
parentKey 父表中字段名称

dataNode标签

datanode标签定义了mycat中的数据节点,也就是我们所说的数据分片。一个datanode标签就是一个独立的数据分片。
name 定义数据节点的名字,这个名字需要唯一。我们在table标签上用这个名字来建立表与分片对应的关系
dataHost 用于定义该分片属于哪个数据库实例,属性与datahost标签上定义的name对应
database 用于定义该分片属于数据库实例上 的具体库。

dataHost标签
这个标签直接定义了具体数据库实例,读写分离配置和心跳语句。

<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="192.168.1.100:13306" user="root" password="123456">
<readHost host="hostS1" url="192.168.1.101:13307" user="root" password="123456" />
<readHost host="hostS1" url="192.168.1.101:13307" user="root" password="123456" />
</writeHost>
<writeHost host="hostM1" url="192.168.1.102:13308" user="root" password="123456"></writeHost>
</dataHost>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

name 唯一标示dataHost标签,供上层使用
maxCon 指定每个读写实例连接池的最大连接。
minCon 指定每个读写实例连接池的最小连接,初始化连接池的大小
balance 读取数据负载均衡
balance=“0”:不开启读写分离机制,所有读操作都发送到当前可用的writeHost上
balance=“1”:全部的readHost与stand by writeHost参与select语句的负载均衡,简单的说,当双主双从模式(M1-S1,M2-S2 并且M1 M2互为主备),正常情况下,M2,S1,S2都参与select语句的负载均衡。
balance=“2”:所有读操作都随机的在writeHost、readHost上分发
balance=“3”:所有读请求随机的分发到writeHost对应的readHost执行,writeHost不负担读写压力。(1.4之后版本有)
writeType 写操作负载均衡
writeType=“0”, 所有写操作发送到配置的第一个 writeHost,第一个挂了切到还生存的第二个writeHost,重新启动后已切换后的为准,切换记录在配置文件中:dnindex.properties .
writeType=“1”,所有写操作都随机的发送到配置的 writeHost。1.5以后版本废弃不推荐。

1)heartbeat标签
这个标签内指明用于和后端数据库进行心跳检查的语句。
例如:MYSQL 可以使用 select user(),Oracle 可以使用 select 1 from dual 等。
2) writeHost /readHost 标签
这两个标签都指定后端数据库的相关配置,用于实例化后端连接池。唯一不同的是,writeHost 指定写实例、readHost 指定读实例。
在一个 dataHost 内可以定义多个 writeHost 和 readHost。但是,如果 writeHost 指定的后端数据库宕机,那么这个 writeHost 绑定的所有 readHost 都将不可用。
另一方面,由于这个 writeHost 宕机,系统会自动的检测到,并切换到备用的 writeHost 上去。这两个标签的属性相同,这里就一起介绍。

–host 用于标识不同实例,一般 writeHost 我们使用M1,readHost 我们用S1。
–url 后端实例连接地址。Native:地址:端口 JDBC:jdbc的url
–password 后端存储实例需要的密码
–user 后端存储实例需要的用户名字
–weight 权重 配置在 readhost 中作为读节点的权重
–usingDecrypt 是否对密码加密,默认0。具体加密方法看官方文档。
3、rule.xml的配置
tableRule 标签
这个标签定义表分片规则。

<tableRule name="rule1">
<rule>
<columns>id</columns>
<algorithm>func1</algorithm>
</rule>
</tableRule>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

name 属性指定唯一的名字,用于标识不同的表规则。
内嵌的 rule 标签则指定对物理表中的哪一列进行拆分和使用什么路由算法。
columns 内指定要拆分的列名字。
algorithm 使用 function 标签中的 name 属性。连接表规则和具体路由算法。当然,多个表规则可以连接到同一个路由算法上。table 标签内使用。让逻辑表使用这个规则进行分片。
function 标签

<function name="hash-int" class="io.mycat.route.function.PartitionByFileMap">
<property name="mapFile">partition-hash-int.txt</property>
</function>
  • 1
  • 2
  • 3

name 指定算法的名字。
class 制定路由算法具体的类名字。
property 为具体算法需要用到的一些属性。
五、使用mycat配置mysql数据库分片
1、单节点无分片配置
将schema.xml文件按照如下方式配置

<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="10">
		<table name="user" dataNode="dn1"/>
</schema>
<dataNode name="dn1" dataHost="host1" database="db1" />
<dataHost name="host1" maxCon="1000" minCon="10" balance="3" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<writeHost host="m1" url="localhost:13306" user="root" password="">
			<readHost host="s1" url="localhost:13307" user="root" password="" />
		</writeHost>
</dataHost>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

2、多节点分片配置
将schema.xml文件按照如下方式配置
要进行多节点分片设置必须保证主从数据库的数据库名称一致,如果节点之间要互为备份则节点与节点的数据库名称也要一致。

<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="10">
		<table name="user" primaryKey="id" autoIncrement="true"  dataNode="dn1,dn2" rule="mod-long" />
	</schema>
	<dataNode name="dn1" dataHost="host1" database="db1" />
	<dataNode name="dn2" dataHost="host2" database="db1" />
	<dataHost name="host1" maxCon="1000" minCon="10" balance="3" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
		<heartbeat>select user()</heartbeat>
		<writeHost host="m1" url="localhost:13306" user="root" password="">
		    <readHost host="s1" url="localhost:13307" user="root" password="" />
		</writeHost>
		<writeHost host="m2" url="localhost:13308" user="root" password=""></writeHost>
	</dataHost>
<dataHost name="host2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
		 <heartbeat>select user()</heartbeat>
		 <writeHost host="m2" url="localhost:13308" user="root" password="">
			<readHost host="s2" url="localhost:13309" user="root" password="" />
         </writeHost>
		 <writeHost host="m1" url="localhost:13306" user="root" password=""></writeHost>
	</dataHost>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

注意:如果配置了多节点分片,那么mysql默认的自增长方式就失效了,原因很简单如果仍然使用mysql自己的自增长,因为数据在不同的数据库中,每个数据库按照自己的规则进行自增。那么很容易出现主键冲突的问题。
所以我们要使用mycat提供的自增长,以下我们介绍一种使用mycat本地文件的方式来实现分片主键自增。
1.修改server.xml将0修改为0
2.修改schema.xml中table标签,添加autoIncrement=”true”和primaryKey=”id”属性,目的是开启mycat主键自增以及配置主键字段名称
3.打开sequence_conf.properties文件添加一段配置
USER.HISIDS=
USER.MINID=1001
USER.MAXID=2000
USER.CURID=1000
这段配置中USER为表名,USER.MINID为自增起始位置,USER.MAXID为自增结束位置,USER.CURID为当前值。

注意:在mycat中如果有关联表为了解决join问题,可以采用ER表来处理。如下:

<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="10">
		<table name="user" autoIncrement="true" primaryKey="id" dataNode="node1,node2" rule="mod-long" >
			<childTable name="orders" autoIncrement="true" primaryKey="id" joinKey="uid" parentKey="id" >
				<childTable name="orderitem" autoIncrement="true" primaryKey="id" joinKey="oid" parentKey="id" />
			</childTable>
		</table>
</schema>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

使用上述配置,可以保证和用户相关的的订单会保存在该用户的同一个节点中,和订单相关的订单详情也会保存在该订单的同一个节点中。

无论你在学习上有任何问题,重庆蜗牛学院欢迎你前来咨询,联系QQ:296799112

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/400425
推荐阅读
相关标签
  

闽ICP备14008679号