为了把MySQL分库分表:MyCAT学明白,我花了近一个月的时间!
MySQL分库分表:MyCAT-问题描述
随着数据库存储的内容越来越多,MySQL主从复制也开始无法存储更多的数据,此时就需要切割表,把一张过大的表切割后分别存储在不同的MySQL中,以便存储更多的内容,承载更多的用户。此阶段出现的典型问题如下:
(1)随着互联网的发展,数据的量级也呈指数级增长,从GB到TB再到PB。对数据的各种操作也愈加困难,传统的关系数据库已经无法满足快速查询与插入数据的需求。如何使单表数据量存储更大?甚至期望单表数据量可以“无限扩大”。
(2)MySQL本身是不支持读写分离的,MySQL只支持主从数据复制,读写功能需要重新开发,。有没有一种办法可以不用一次次重写这部分切面代码?
(3)如何保证集群的中间件不宕机?一旦中间件崩溃,所有的MySQL节点就都无法提供服务了,因为Java代码连接的是MyCAT中间件的地址,对这部分高可用的需求该如何解决?
问题分析与解决方案
针对在8.1节中出现的问题,使用分库分表即可解决。在国内市场上,分库分表与分布式事务通常使用MyCAT来解决。MyCAT是基于阿里巴巴开源的Cobar产品研发的,Cobar的稳定性、可靠性、优秀的架构和性能,以及众多成熟的使用案例使得MyCAT一开始就拥有一个很好的起点。
MyCAT支持MySQL、Oracle、DB2、SQL Server、PostgreSQL等数据库的常见SQL语法,支持读写分离、MySQL主从复制、Galera Cluster集群、XA分布式事务、全局序列号(分布式下的主键生成问题)、数据库分片、密码加密、服务降级、IP地址白名单、SQL黑名单、SQL注入攻击拦截、预编译指令、PostgreSQL的Native协议、存储过程、协调主从切换、Zookeeper序列化、库内分表等相关功能。
MyCAT可以解决分布式事务、读写分离、主从、分片等一系列MySQL集群和分布式问题。MyCAT的操作十分简单,Spring Boot微服务的数据源连接池只操作MyCAT即可。MyCAT会提供给Spring Boot相关地址作为虚拟数据库使用,MyCAT虚拟数据库会通过逻辑的方式操作下属N个MySQL数据库。例如,设置MyCAT分片规则为每500万条数据就换一个数据库进行存储(多库多表的纵向分割),实际上,Spring Boot代码认为自身操作的还是一张表(MyCAT提供的虚拟表)。
在使用MyCAT对数据进行分片处理之后,一个数据库会被切分为多个分片数据库,所有的分片数据库集群构成一个完整的数据库存储。使用MyCAT搭建的一主多从环境架构图如图8-1所示。
图8-1
在搭建完MyCAT架构之后,应用程序(Java、PHP)可通过MyCAT数据中间件地址与账号密码,如同使用正常MySQL一般使用MyCAT,除配置信息外,不需要修改任何代码。MyCAT给应用程序提供的逻辑库与逻辑表,本质上相当于先从应用程序处接收到SQL语句,然后通过各个MySQL主机与主机下的分片进行数据整合,最后将整合后的数据返回给应用程序。
MyCAT提供的表为逻辑表,库为逻辑库,本质上都是不存在的。
MyCAT实战---构建MyCAT一主多从架构
准备三台Linux服务器,其中,将两台服务器作为MySQL,另外一台用来安装MyCAT中间件。
从MyCAT下载地址处下载MyCAT的安装包,如图8-2所示。
图8-2
将下载的MyCAT安装包放入Linux服务器中,并通过tar -zxvf命令进行解压缩,得到mycat文件夹,如图8-3所示。
图8-3
MyCAT的目录结构如表8-1所示。
表8-1
进入MyCAT文件夹的bin目录下,通过命令启动MyCAT脚本。MyCAT的启动命令如下所示:
其他命令如下所示:
如果出现successfully,则说明已启动正常:
MyCAT的关闭命令如下所示:
1. 初次启动MyCAT容易出现的部分错误及解决方式
初次启动MyCAT容易出现的部分错误及解决方式如下。
(1)没有安装JDK。如果出现如下错误提示,则很可能是没有安装JDK:
解决方式:如果已安装JDK,仍然出现上面的错误,则有可能是JDK的相关环境变量不在Linux系统的root账号下所导致的,此时应重新对JDK进行配置。
(2)无法指定Java环境。如果出现如下错误提示,则有可能是MyCAT无法指向JDK的Java程序:
解决方式:打开MyCAT的conf目录下的wrapper.conf文件,并在文件中修改如下代码:
把目录直接指向Java程序,即可解决该问题。
(3)堆栈空间不足。如果出现如下错误提示,则有可能JVM的堆栈空间不足:
解决方式:打开MyCAT的conf目录下的wrapper.conf文件,并在文件中修改或加入如下代码:
增加初始化JVM的堆栈空间,即可解决该问题。
(4)权限不足。如果出现如下错误提示,则有可能是MyCAT在修改某些文件时没有Linux系统的一些权限:
解决方式:使用root赋予其相关权限,或者切换到root账号,即可解决该问题。此外,也有可能是因为wrapper.conf文件没有指向Java可执行文件,此时把wrapper.java.command指向Java_Home的bin目录下的可执行文件即可。
(5)配置文件错误。如果出现如下错误提示,则有可能是MyCAT自身配置文件编写有误:
解决方式:重新编写配置文件,若初次执行启动就遇到该错误,则建议重新下载MyCAT。
(6)主机名错误。如果出现如下错误提示,则有可能是Linux系统的hostName配置出现了异常:
解决方式:
① 修改/etc/sysconfig/network文件,追加如下代码:
② 修改/etc/hosts文件,修改如下代码:
(7)JDK版本问题。如果出现如下错误提示,则有可能是Linux系统的JDK版本出现了异常:
解决方式:在wrapper.conf配置文件中删掉XX:MaxPermSize配置,如图8-4所示。
图8-4
在JDK1.8(或者称JDK8.0)版本之后,取消了永久区,进而使JVM无法识别永久区参数MaxPermSize。
2. MyCAT的基本信息配置
在MyCAT中,与MySQL相关的配置文件主要有三个:
• schema.xml:定义逻辑库、表、分片节点等内容。
• rule.xml:定义分片规则。
• server.xml:定义用户和系统的相关变量,如端口(默认为8066)等。
(1)配置MyCAT的schema.xml。schema.xml中主要记录了主从库等相关信息。本节使用一主两从架构环境,按照7.5节的配置环境填写如下schema信息:
从上面的schema.xml配置文件可以看出,writeHost为写入节点,其内部为写入节点的主从复制读取的readHost节点。
需要注意的是,在schema.xml配置文件中,参数与参数之间要有空格,否则会出现如下错误提示:
通过上述错误提示可以看到,xml文件的第7行第21个字符出现了问题,需要修改dataNode标签中的属性。
schema标签可用来定义MyCAT实例中的逻辑库。MyCAT可以有多个逻辑库,每个逻辑库都有自己的相关配置。可以使用schema标签来划分这些不同的逻辑库。如果不配置schema标签,则所有的表都属于同一个默认的逻辑库。逻辑库的概念和MySQL的database的概念一样,即在查询两个不同的逻辑库中的表时,需要切换到该逻辑库下进行查询。
schema标签的name属性为Java代码通过MyCAT访问看到的数据库名(逻辑库名)。逻辑库名和后端物理库名可能不同,也可能对应多个后端物理库。
同一个实例下的物理数据库名称不能重复,同理,schema的逻辑库名也不能重复。此处,name属性为自定义的,与实际后端可能不同,访问时以schema标签的name属性为准。
如果在SQL语句中不含limit参数,则默认设置limit参数为sqlMaxLimit属性所对应的数值。如果运行的schema为非拆分库,则sqlMaxLimit属性不会生效,需要自己通过SQL语句加limit。server.xml中的limit是整个MyCAT系统的默认值,此处是当前逻辑库的默认值,默认先看schema.xml的限制数。
schema标签的dataNode属性为逻辑库对应的分片。如果需要配置多个分片,则只需多个dataNode即可:
schema标签的dataNode属性配置为表切分后,还需要配置映射到哪几个数据库中。MyCAT的分片实际上就是库的别名。例如,上面例子配置了两个分片,即dn1和dn2,它们分别对应物理机映射dataHost localhost1的两个库。
另外,其name参数的“dn1”值理应对应dataNode标签。
当schema标签的checkSQLschema属性为true时,MyCAT会修改执行的数据库语句,如下所示:
dataNode标签是实际的物理库配置地址,可以配置多主、主从等其他配置。多个dataHost代表分片对应的物理库地址,下面的writeHost、readHost代表该分片是否配置多写、主从、读写分离等高级特性。
dataNode标签
name参数为自定义的唯一值。在需要分库时,该名称将用来建立表与分片之间的关系。
dataHost参数用来定义该分片属于哪个数据库实例,属性与在datahost标签上定义的name对应。
database参数用来定义该分片属于哪个数据库实例上的具体库。另外,如果没有提前配置