关于java:手把手带你用数据库中间件MycatSpringBoot完成分库分表

37次阅读

共计 5468 个字符,预计需要花费 14 分钟才能阅读完成。

我的公众号:MarkerHub,网站:https://markerhub.com

更多精选文章请点击:Java 笔记大全.md

Cat 哥领读:

挺具体的入门材料,手把手教学!


  • 作者:叩丁狼教育 蓝雄威
  • https://www.jianshu.com/p/f81…

一、背景

随着工夫和业务的倒退,数据库中的数据量增长是不可控的,库和表中的数据会越来越大,随之带来的是更高的磁盘、IO、零碎开销,甚至性能上的瓶颈,而一台服务的资源究竟是无限的,因而须要对数据库和表进行拆分,从而更好的提供数据服务。

当用户表白到千万级别,在做很多操作的时候都会很吃力,所以当数据增长到 1000 万以上就须要分库分表来缓解单库(表)的压力。

二、什么是分库分表

简略来说,就是指通过某种特定的条件,将咱们寄存在同一个数据库中的数据扩散寄存到多个数据库(主机)下面,以达到扩散单台设施负载的成果。

数据的切分(Sharding)依据其切分规定的类型,能够分为两种切分模式。一种是依照不同的表(或者 Schema)来切分到不同的数据库(主机)之上,这种切能够称之为数据的垂直(纵向)切分;另外一种则是依据表中的数据的逻辑关系,将同一个表中的数据依照某种条件拆分到多台数据库(主机)下面,这种切分称之为数
据的程度(横向)切分。

垂直切分的最大特点就是规定简略,施行也更为不便,尤其适宜各业务之间的耦合度非常低,相互影响很小,业务逻辑十分清晰的零碎。在这种零碎中,能够很容易做到将不同业务模块所应用的表分拆到不同的数据库中。依据不同的表来进行拆分,对应用程序的影响也更小,拆分规定也会比较简单清晰。

程度切分于垂直切分相比,相对来说略微简单一些。因为要将同一个表中的不同数据拆分到不同的数据库中,对于应用程序来说,拆分规定自身就较依据表名来拆分更为简单,前期的数据保护也会更为简单一些。

三、垂直切分

个数据库由很多表的形成,每个表对应着不同的业务,垂直切分是指依照业务将表进行分类,散布到不同
的数据库下面,这样也就将数据或者说压力分担到不同的库下面,如下图:

零碎被切分成了,用户,订单交易,领取几个模块。
一个架构设计较好的利用零碎,其总体性能必定是由很多个功能模块所组成的,而每一个功能模块所须要的数据对应到数据库中就是一个或者多个表。而在架构设计中,各个功能模块相互之间的交互点越对立越少,零碎的耦合度就越低,零碎各个模块的维护性以及扩展性也就越好。这样的零碎,实现数据的垂直切分也就越容易。

然而往往零碎之有些表难以做到齐全的独立,存在这扩库 join 的状况,对于这类的表,就须要去做均衡,是数据库退让业务,共用一个数据源,还是分成多个库,业务之间通过接口来做调用。在零碎初期,数据量比拟少,或者资源无限的状况下,会抉择共用数据源,然而当数据倒退到了肯定的规模,负载很大的状况,就需
要必须去做宰割。

一般来讲业务存在着简单 join 的场景是难以切分的,往往业务独立的易于切分。如何切分,切分到何种
水平是考验技术架构的一个难题。
上面来剖析下垂直切分的优缺点:

长处

拆分后业务清晰,拆分规定明确;

零碎之间整合或扩大容易;

数据保护简略。

毛病

局部业务表无奈 join,只能通过接口方式解决,进步了零碎复杂度;

受每种业务不同的限度存在单库性能瓶颈,不易数据扩大跟性能进步;

事务处理简单。

因为垂直切分是依照业务的分类将表扩散到不同的库,所以有些业务表会过于宏大,存在单库读写与存储瓶颈,所以就须要程度拆分来做解决。

四、程度切分

绝对于垂直拆分,程度拆分不是将表做分类,而是依照某个字段的某种规定来扩散到多个库之中,每个表中蕴含一部分数据。简略来说,咱们能够将数据的程度切分了解为是依照数据行的切分,就是将表中的某些行切分到一个数据库,而另外的某些行又切分到其余的数据库中,如图

拆分数据就须要定义分片规定。关系型数据库是行列的二维模型,拆分的第一准则是找到拆分维度。比方:
从会员的角度来剖析,商户订单交易类零碎中查问会员某天某月某个订单,那么就须要依照会员联合日期来拆分,不同的数据依照会员 ID 做分组,这样所有的数据查问 join 都会在单库内解决;如果从商户的角度来讲,要查问某个商家某天所有的订单数,就须要依照商户 ID 做拆分;然而如果零碎既想按会员拆分,又想按商家数据,则会有肯定的艰难。如何找到适合的分片规定须要综合思考衡。
几种典型的分片规定包含:

依照用户 ID 求模,将数据扩散到不同的数据库,具备雷同数据用户的数据都被扩散到一个库中;

依照日期,将不同月甚至日的数据扩散到不同的库中;

依照某个特定的字段求摸,或者依据特定范畴段扩散到不同的库中。

如图,切分准则都是依据业务找到适宜的切分规定扩散到不同的库,上面用用户 ID 求模举

既然数据做了拆分有长处也就优缺点。
长处

拆分规定形象好,join 操作根本能够数据库做;

不存在单库大数据,高并发的性能瓶颈;

利用端革新较少;

进步了零碎的稳定性跟负载能力。

毛病

拆分规定难以形象;

分片事务一致性难以解决;

数据屡次扩大难度跟保护量极大;

跨库 join 性能较差

五、什么是 Mycat

它是一个开源的分布式数据库系统,是一个实现了 MySQL 协定的的
Server,前端用户能够把它看作是一个数据库代理,用 MySQL 客户端工具和命令行拜访,而其后端能够用 MySQL 原生(Native)协定与多个 MySQL 服务器通信,也能够用 JDBC 协定与大多数支流数据库服务器通信,其外围性能是分表分库,行将一个大表程度宰割为 N 个小表,存储在后端 MySQL 服务器里或者其余数据库里。

常见利用场景:

单纯的读写拆散,此时配置最为简略,反对读写拆散,主从切换;

分表分库,对于超过 1000 万的表进行分片,最大反对 1000 亿的单表分片;

多租户利用,每个利用一个库,但应用程序只连贯 Mycat,从而不革新程序自身,实现多租户化;

报表零碎,借助于 Mycat 的分表能力,解决大规模报表的统计; 代替 Hbase,剖析大数据;

作为海量数据实时查问的一种简略无效计划,比方 100 亿条频繁查问的记录须要在 3 秒内查问进去后果,除了基于主键的查问,还可能存在范畴查问或其余属性查问,此时 Mycat 可能是最简略无效的选

六、SpringBoot+Mycat+MySQL 实现分表分库案例

对于分库分表,Mycat 曾经帮咱们在外部实现了路由的性能,咱们只须要在 Mycat 中配置以下切分规定即可,对于开发者来说,咱们就能够把 Mycat 看做是一个数据库,接下来咱们开始搭建环境:

步骤一:

Mycat 是应用 java 写的数据库中间件,所以要运行 Mycat 前要筹备要 jdk 的环境,要求是 jdk1.7 以上的环境。所以须要在零碎中配置 JAVA_HOME 的环境变量.

步骤二:

从官网下载 Mycat,http://dl.mycat.io/1.6-RELEASE / 咱们是基于 CentOS7 来搭建 Mycat 环境的,所以下载版本:
Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz

步骤三:

将下载好的安装包上传到服务器上并解压. 解压之后目录构造如下:

步骤四:

配置切分规定:
将如下配置复制粘贴笼罩 mycat/conf/schema.xml 的内容。

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

   <schema >
           <table  />  
   </schema>
   
   <!-- 设置 dataNode 对应的数据库, 及 mycat 连贯的地址 dataHost -->  
   <dataNode  />  
   <dataNode  />  
   
   <!-- mycat 逻辑主机 dataHost 对应的物理主机. 其中也设置对应的 mysql 登陆信息 -->  
   <dataHost >  
           <heartbeat>select user()</heartbeat>  
           <writeHost host="server1" url="127.0.0.1:3306" user="root" password="WolfCode_2017"/>  
   </dataHost>
</mycat:schema>

<schema>: 示意的是在 mycat 中的逻辑库配置,逻辑库名称为:TESTDB

<table>: 示意在 mycat 中的逻辑表配置,逻辑表名称为:user, 映射到两个数据库节点 dataNode 中, 切分规定为:rule1(在 rule.xml 配置)

<dataNode>: 示意数据库节点, 这个节点不肯定是单节点,能够配置成读写拆散.

<dataHost>: 实在的数据库的地址配置

<heartbeat>: 用户心跳检测

<writeHost>: 写库的配置

将如下配置复制粘贴笼罩 mycat/conf/rule.xml 的内容。

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:rule SYSTEM "rule.dtd">
<mycat:rule xmlns:mycat="http://io.mycat/">
   <tableRule >
       <rule>
           <columns>id</columns>
           <algorithm>mod-long</algorithm>
       </rule>
   </tableRule>
   <function >
       <!-- how many data nodes -->
       <property >2</property>
   </function>
</mycat:rule>

这里定义的是切分规定,是依照 id 列进行切分,切分规定是采取取模的形式,
<property >2</property>: 这里配置了咱们有拆分了多个库 (表),须要和后面配置
<table />
中的 dataNode 个数统一,否则会出错.

步骤五:

在数据库中创立两个数据库 db01,db02.
每个库中执行如下建表语句:

CREATE TABLE `user` (`id` bigint(20) NOT NULL,
 `name` varchar(255) DEFAULT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

步骤六:

启动 mycat, 执行mycat/bin/startup_nowrap.sh

步骤七:

我的项目曾经上传到 github
https://github.com/javalanxio…
搭建 SpringBoot 环境,执行插入语句.
application.properties配置如下:

# 配置数据源
spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver
#这里配置的是 Mycat 中 server.xml 中配置账号密码,不是数据库的明码。spring.datasource.druid.username=root
spring.datasource.druid.password=123456
#mycat 的逻辑库 端口也是 mycat 的
spring.datasource.druid.url=jdbc:mysql://192.168.142.129:8066/TESTDB

UserMapper.java 代码如下:

@Mapper
public interface UserMapper {@Insert("insert into user(id,name) value (#{id},#{name})")
   int insert(User user);
   @Select("select * from user")
   List<User> selectAll();}

UserController.java 代码如下:

@RestController
@RequestMapping("/user")
public class UserController {
   @Autowired
   private UserMapper userMapper;
   @RequestMapping("/save")
   public String save(User user){userMapper.insert(user);
       return "保留胜利";
   }
   @RequestMapping("/list")
   public List<User> list(){return userMapper.selectAll();
   }
}

步骤八:

测试:
在地址栏输出: http://localhost:8080/user/save?id=1&name=tom
http://localhost:8080/user/save?id=2&name=jack
查看数据库发现:
id 为 1 的数据插入到数据库 db02 中的 user 表。
id 为 2 的数据插入到数据库 db01 中的 user 表。
在地址栏输出:
http://localhost:8080/user/list
是能够看到刚刚插入的两条记录.

好到这一步咱们就曾经实现了分表分库了.


(完)

举荐浏览

Java 笔记大全.md

太赞了,这个 Java 网站,什么我的项目都有!https://markerhub.com

这个 B 站的 UP 主,讲的 java 真不错!

太赞了!最新版 Java 编程思维能够在线看了!

正文完
 0