手摸手教你你用数据库中间件Mycat SpringBoot完成分库分表

优质文章,第一时间送达

关注公众号后台回复paymall获取实战项目资料+视频

作者:叩丁狼教育 蓝雄威

https://www.jianshu.com/p/f81422b1c915

一、背景

随着时间和业务的发展,数据库中的数据量增长是不可控的,库和表中的数据会越来越大,随之带来的是更高的磁盘、IO、系统开销,甚至性能上的瓶颈,而一台服务的资源终究是有限的,因此需要对数据库和表进行拆分,从而更好的提供数据服务。

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

二、什么是分库分表

简单来说,就是指通过某种特定的条件,将我们存放在同一个数据库中的数据分散存放到多个数据库(主机)上面,以达到分散单台设备负载的效果。

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

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

水平切分于垂直切分相比,相对来说稍微复杂一些。因为要将同一个表中的不同数据拆分到不同的数据库中,对于应用程序来说,拆分规则本身就较根据表名来拆分更为复杂,后期的数据维护也会更为复杂一些。

三、垂直切分

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

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

但是往往系统之有些表难以做到完全的独立,存在这扩库 join 的情况,对于这类的表,就需要去做平衡,是数据库让步业务,共用一个数据源,还是分成多个库,业务之间通过接口来做调用。在系统初期,数据量比较少,或者资源有限的情况下,会选择共用数据源,但是当数据发展到了一定的规模,负载很大的情况,就需
要必须去做分割。

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

优点

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

系统之间整合或扩展容易;

数据维护简单。

缺点

部分业务表无法 join,只能通过接口方式解决,提高了系统复杂度;

受每种业务不同的限制存在单库性能瓶颈,不易数据扩展跟性能提高;

事务处理复杂。

由于垂直切分是按照业务的分类将表分散到不同的库,所以有些业务表会过于庞大,存在单库读写与存储瓶颈,所以就需要水平拆分来做解决。

四、水平切分

相对于垂直拆分,水平拆分不是将表做分类,而是按照某个字段的某种规则来分散到多个库之中,每个表中包含一部分数据。简单来说,我们可以将数据的水平切分理解为是按照数据行的切分,就是将表中的某些行切分到一个数据库,而另外的某些行又切分到其他的数据库中,如图

搜索公纵号:MarkerHub,关注回复[ vue ]获取前后端入门教程!

拆分数据就需要定义分片规则。关系型数据库是行列的二维模型,拆分的第一原则是找到拆分维度。比如:
从会员的角度来分析,商户订单交易类系统中查询会员某天某月某个订单,那么就需要按照会员结合日期来拆分,不同的数据按照会员 ID 做分组,这样所有的数据查询 join 都会在单库内解决;如果从商户的角度来讲,要查询某个商家某天所有的订单数,就需要按照商户 ID 做拆分;但是如果系统既想按会员拆分,又想按商家数据,则会有一定的困难。如何找到合适的分片规则需要综合考虑衡。
几种典型的分片规则包括:

按照用户 ID 求模,将数据分散到不同的数据库,具有相同数据用户的数据都被分散到一个库中;

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

按照某个特定的字段求摸,或者根据特定范围段分散到不同的库中。

如图,切分原则都是根据业务找到适合的切分规则分散到不同的库,下面用用户 ID 求模举

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

拆分规则抽象好,join 操作基本可以数据库做;

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

应用端改造较少;

提高了系统的稳定性跟负载能力。

缺点

拆分规则难以抽象;

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

数据多次扩展难度跟维护量极大;

跨库 join 性能较差

五、什么是 Mycat

它是一个开源的分布式数据库系统,是一个实现了 MySQL 协议的的
Server,前端用户可以把它看作是一个数据库代理,用 MySQL 客户端工具和命令行访问,而其后端可以用 MySQL 原生(Native)协议与多个 MySQL 服务器通信,也可以用 JDBC 协议与大多数主流数据库服务器通信,其核心功能是分表分库,即将一个大表水平分割为 N 个小表,存储在后端 MySQL 服务器里或者其他数据库里。

常见应用场景:

单纯的读写分离,此时配置最为简单,支持读写分离,主从切换;

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

多租户应用,每个应用一个库,但应用程序只连接 Mycat,从而不改造程序本身,实现多租户化;

搜索公纵号:MarkerHub,关注回复[ vue ]获取前后端入门教程!

报表系统,借助于 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/javalanxiongwei/springboot-mycat
搭建 SpringBoot 环境,执行插入语句.
application.properties配置如下:

#配置数据源spring.datasource.druid.driver-class-name=com.mysql.jdbc.Driver#这里配置的是Mycat中server.xml中配置账号密码,不是数据库的密码。spring.datasource.druid.username=rootspring.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 8 并行流吧,让执行速度飞起!

Java实现QQ登录和微博登录

推荐 5 款好用的REST API工具

一口气说了 6种 数据脱敏方案,大厂也这么用!

新技能 MyBatis 千万数据表,快速分页!

2020搞个 Mac 玩玩

10w行级别数据的Excel导入,4版完整优化记录,效果太明显了!

用Java实现一个抽奖系统(附完整代码)

(0)

相关推荐

  • 分库分表之第一篇

    分库分表之第一篇

  • 手摸手教你做一个超火的酷炫视频,一键生成!

    昨天中秋,再给大家补上一句中秋快乐,虽然这调休出来的三天假期挺短的,但我是好好休息了一下. 不过这三天我也不是啥都没干,前两天刚放假的时候,把家里的神兽送到了我爸妈那,然后无事一身轻的我躺床上准备找个 ...

  • 超简单的 Office 下载安装激活一条龙,手摸着手教你搞定!

    自从最近给大家安利了可以<一劳永逸的 Win10 完美激活工具>和<从微软官网下载 Win10 >的方法之后,很多小伙伴都在留言追问有没有 Office 的激活方法. 理解,O ...

  • 手摸着手教你开通微信支付分,比比谁最高?

    支付宝的芝麻信用大家都知道吧,只要积累到了一定分数,就可以免押金骑共享单车.住酒店,而且很多服务可以先享用后付费,非常方便. 相比来说,微信这一点就差远了. 不过呢,微信终于也出了和芝麻信用类似的服务 ...

  • 福利!手摸着手教你在线看豆瓣全站电影!(附工具下载)

    又到周末了,天又冷,宅在家里看几部电影最舒服不过了,网黑哥经常会去豆瓣找冷门高分片来看,每次再去搜资源下载,有时候下下来一看感觉又不对口味,来来回回挺折腾时间的,要是豆瓣全站的电影能不用下载,即点即看 ...

  • 手摸手带你理解Vue的Watch原理

    前言 watch 是由用户定义的数据监听,当监听的属性发生改变就会触发回调,这项配置在业务中是很常用.在面试时,也是必问知识点,一般会用作和 computed 进行比较. 那么本文就来带大家从源码理解 ...

  • 手摸手带你理解Vue响应式原理

    前言 响应式原理作为 Vue 的核心,使用数据劫持实现数据驱动视图.在面试中是经常考查的知识点,也是面试加分项. 本文将会循序渐进的解析响应式原理的工作流程,主要以下面结构进行: 分析主要成员,了解它 ...

  • 数据库的分库分表思想,高级工程师必备

    前言 关系型数据库本身比较容易成为系统瓶颈,单机存储容量.连接数.处理能力都有限.当单表的数据量达到1000W或100G以后,由于查询维 度较多,即使添加从库.优化索引,做很多操作时性能仍下降严重.此 ...

  • 数据库:我都快爆了,你为什么还不分库分表?

    在文章开头先抛几个问题: 什么时候才需要分库分表呢?我们的评判标准是什么? 一张表存储了多少数据的时候,才需要考虑分库分表? 数据增长速度很快,每天产生多少数据,才需要考虑做分库分表? 这些问题你都搞 ...

  • 基于SpringCloud实现Shard-Jdbc的分库分表模式,数据库扩容方案

    本文源码:GitHub·点这里 || GitEE·点这里 一.项目结构 1.工程结构 2.模块命名 shard-common-entity: 公共代码块 shard-open-inte: 开放接口管理 ...