Mysql分库分表(Mycat)
目录
一.分库分表概述及Mycat的概述
1.数据切分方式
2.MyCAT概述
二.部署MyCAT服务
1.环境准备
2.配置MyCat服务器
3.分片规则
1)枚举法
2)求模法
3)全局表
一.分库分表概述及Mycat的概述
关系型数据库本身比较容易成为系统瓶颈,单机存储容量、连接数、处理能力都有限。
当单表的数据量达到1000W或100G以后,由于查询维度较多,即使添加从库、优化索引,做很多操作时性能仍下降严重。此时就要考虑对其进行切分了,切分的目的就在于减少数据库的负担,缩短查询时间。
数据库分布式核心内容无非就是数据切分(Sharding),以及切分后对数据的定位、整合。
数据切分就是将数据分散存储到多个数据库中,使得单一数据库中的数据量变小,通过扩充主机的数量缓解单一数据库的性能问题,从而达到提升数据库操作性能的目的。
1.数据切分方式
垂直(纵向)切分
垂直切分常见有垂直分库和垂直分表两种。
垂直分库就是根据业务耦合性,将关联度低的不同表存储在不同的数据库。做法与大系统拆分为多个小系统类似,按业务分类进行独立划分。
垂直分表是基于数据库中的"列"进行,某个表字段较多,可以新建一张扩展表,将不经常用或字段长度较大的字段拆分出去到扩展表中。
垂直切分的优点:
解决业务系统层面的耦合,业务清晰
对不同业务的数据进行分级管理、维护、监控、扩展等
高并发场景下,垂直切分一定程度的提升IO、数据库连接数、单机硬件资源的瓶颈
垂直切分的缺点:
部分表无法join,只能通过接口聚合方式解决,提升了开发的复杂度
分布式事务处理复杂
依然存在单表数据量过大的问题(需要水平切分)
水平(横向)切分
当一个应用难以再细粒度的垂直切分,或切分后数据量行数巨大,存在单库读写、存储性能瓶颈,这时候就需要进行水平切分了。
水平切分分为库内分表和分库分表,是根据表内数据内在的逻辑关系,将同一个表按不同的条件分散到多个数据库或多个表中,每个表中只包含一部分数据,从而使得单个表的数据量变小,达到分布式的效果。
库内分表只解决了单一表数据量过大的问题,但没有将表分布到不同机器的库上,因此对于减轻MySQL数据库的压力来说,帮助不是很大,大家还是竞争同一个物理机的CPU、内存、网络IO,最好通过分库分表来解决。
水平切分后同一张表会出现在多个数据库/表中,每个库/表的内容不同。
水平切分的优点:
不存在单库数据量过大、高并发的性能瓶颈,提升系统稳定性和负载能力
应用端改造较小,不需要拆分业务模块
水平切分的缺点:
跨分片的事务一致性难以保证
跨库的join关联查询性能较差
数据多次扩展难度和维护量极大
2.MyCAT概述
mycat是基于Java的分布式数据库系统中间件,为高并发环境的分布式存储提供解决方案
适合数据大量写入的存储需求
支持MySQL、Oracle、Sqlserver、Mongodb等
提供数据读写分离服务
提供数据分片服务
基于阿里巴巴Cobar进行研发的开源软件
分片规则
枚举法 sharding-by-intfile
固定分片 rule
范围约定 auto-sharding-long
求模法 mod-long
日期列分区法 sharding-by-date
通配取模 sharding-by-pattern
ASCII码求模通配 sharding-by-prefixpattern
编程指定 sharding-by-substring
字符串拆分hash解析 sharding-by-stringhash
一致性hash sharding-by-murmur
工作过程
解析SQL命令涉及到的表
然后看对表的配置,如果有分片规则,则获取SQL命令里分片字段的值,并匹配分片函数,获得分片列表
然后将SQL命令发往对应的数据库服务器去执行
最后收集和处理所有分片结果数据,并返回到客户端
二.部署MyCAT服务
1.环境准备
client:192.168.1.10
mycat:192.168.1.15
db1:192.168.1.11
db2:192.168.1.12
db3:192.168.1.13
2.配置MyCat服务器
部署MyCat 运行环境
[root@mycat1 ~]# yum -y install java-1.8.0-openjdk [root@mycat1 ~]# which java /usr/bin/java [root@mycat1 ~]# java -version openjdk version "1.8.0_222-ea" OpenJDK Runtime Environment (build 1.8.0_222-ea-b03) OpenJDK 64-Bit Server VM (build 25.222-b03, mixed mode)
安装软件包
网址:http://dl.mycat.io/
[root@mycat1 ~]# tar xf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz [root@mycat1 ~]# mv mycat /usr/local/
# 设置PATH环境变量 [root@mycat1 ~]# vim /etc/profile.d/mycat.sh export PATH=$PATH:/usr/local/mycat/bin [root@mycat1 ~]# source /etc/profile.d/mycat.sh
修改配置文件:设置连接账号及逻辑库
# 保持默认配置即可 [root@mycat1 ~]# vim /usr/local/mycat/conf/server.xml # 该文件中用户及逻辑库的说明如下: <user name="root"> <!--连接mycat服务时使用的用户名--><property name="password">123456</property> <!--用户连接mycat用户时使用的密码--><property name="schemas">TESTDB</property> <!--逻辑库名--> </user> <user name="user"><property name="password">user</property><property name="schemas">TESTDB</property><property name="readOnly">true</property> <!--只读权限,连接mycat服务后只有读记录的权限,不写这一行则是可读可写 --> </user>
修改配置文件:配置数据分片
[root@mycat1 ~]# vim /usr/local/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"> <!--对TESTDB库下的表做分片存储 --><!-- auto sharding by id (long) --><table name="travelrecord" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" /> <!-- 对travelrecord表做分片存储 --> <!-- global table is auto cloned to all defined data nodes ,so can joinwith any table whose sharding node is in the same data node --><table name="company" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" /><table name="goods" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" /><!-- random sharding using mod sharind rule --><table name="hotnews" primaryKey="ID" autoIncrement="true" dataNode="dn1,dn2,dn3"rule="mod-long" /><!-- <table name="dual" primaryKey="ID" dataNode="dnx,dnoracle2" type="global"needAddLimit="false"/> <table name="worker" primaryKey="ID" dataNode="jdbc_dn1,jdbc_dn2,jdbc_dn3"rule="mod-long" /> --><table name="employee" primaryKey="ID" dataNode="dn1,dn2,dn3"rule="sharding-by-intfile" /><table name="customer" primaryKey="ID" dataNode="dn1,dn2,dn3"rule="sharding-by-intfile"><childTable name="orders" primaryKey="ID" joinKey="customer_id"parentKey="id"><childTable name="order_items" joinKey="order_id"parentKey="id" /></childTable><childTable name="customer_addr" primaryKey="ID" joinKey="customer_id"parentKey="id" /></table><!-- <table name="oc_call" primaryKey="ID" dataNode="dn1$0-743" rule="latest-month-calldate"/> --></schema><!-- <dataNode name="dn1$0-743" dataHost="localhost1" database="db$0-743"/> --><!-- 定义数据库主机名及存储数据的库 --><dataNode name="dn1" dataHost="mysql1" database="db1" /><dataNode name="dn2" dataHost="mysql2" database="db2" /><dataNode name="dn3" dataHost="mysql3" database="db3" /> <!-- 定义mysql1主机名对应的数据库服务器ip地址 --><dataHost name="mysql1" 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.11:3306" user="mycatadmin"password="NSD2021@tedu.cn"></writeHost></dataHost> <dataHost name="mysql2" maxCon="1000" minCon="10" balance="0"writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"><heartbeat>select user()</heartbeat><writeHost host="hostM2" url="192.168.1.12:3306" user="mycatadmin"password="NSD2021@tedu.cn"></writeHost></dataHost> <dataHost name="mysql3" maxCon="1000" minCon="10" balance="0"writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100"><heartbeat>select user()</heartbeat><writeHost host="hostM3" url="192.168.1.13:3306" user="mycatadmin"password="NSD2021@tedu.cn"></writeHost></dataHost> </mycat:schema>
- 配置数据库服务器
[root@mysql1 ~]# mysql -uroot -pNSD2021@tedu.cn mysql> create database db1 default charset utf8mb4; mysql> grant all on *.* to mycatadmin@'%' identified by 'NSD2021@tedu.cn'; [root@mysql2 ~]# mysql -uroot -pNSD2021@tedu.cn mysql> create database db2 default charset utf8mb4; mysql> grant all on *.* to mycatadmin@'%' identified by 'NSD2021@tedu.cn'; [root@mysql3 ~]# mysql -uroot -pNSD2021@tedu.cn mysql> create database db3 default charset utf8mb4; mysql> grant all on *.* to mycatadmin@'%' identified by 'NSD2021@tedu.cn';
启动MyCat
在MyCat服务器上测试到3台数据库服务器的连接账户
# 安装mysql客户端软件 [root@mycat1 ~]# yum install -y mysql-community-client [root@mycat1 ~]# mysql -h192.168.1.11 -umycatadmin -pNSD2021@tedu.cn [root@mycat1 ~]# mysql -h192.168.1.12 -umycatadmin -pNSD2021@tedu.cn [root@mycat1 ~]# mysql -h192.168.1.13 -umycatadmin -pNSD2021@tedu.cn
启动服务
[root@mycat1 ~]# mycat start [root@mycat1 ~]# netstat -tlnp | grep :8066 tcp6 0 0 :::8066 :::* LISTEN 13835/java
客户端连接测试
[root@node10 ~]# mysql -h192.168.1.15 -P8066 -uroot -p123456 mysql> show databases; +----------+ | DATABASE | +----------+ | TESTDB | +----------+ 1 row in set (0.00 sec)mysql> use TESTDB; mysql> show tables; +------------------+ | Tables in TESTDB | +------------------+ | company | | customer | | customer_addr | | employee | | goods | | hotnews | | orders | | order_items | | travelrecord | +------------------+ 9 rows in set (0.00 sec)
3.分片规则
1)枚举法
概述
使用sharding-by-intfile规则
决定使用枚举法的表
找到数据分片字段名
查看数据分片使用的函数名
找到函数调用的配置文件
修改函数配置文件
配置
查看使用枚举法的表
[root@mycat1 ~]# grep -B1 sharding-by-intfile /usr/local/mycat/conf/schema.xml<table name="employee" primaryKey="ID" dataNode="dn1,dn2,dn3"rule="sharding-by-intfile" /><table name="customer" primaryKey="ID" dataNode="dn1,dn2,dn3"rule="sharding-by-intfile">
查看规则文件,得知sharding-by-intfile分片规则使用的函数
[root@mycat1 ~]# vim /usr/local/mycat/conf/rule.xml <tableRule name="sharding-by-intfile"><rule><columns>sharding_id</columns> <!-- 数据分片字段名 --><algorithm>hash-int</algorithm> <!-- 使用的函数名 --></rule> </tableRule><function name="hash-int"class="io.mycat.route.function.PartitionByFileMap"><property name="mapFile">partition-hash-int.txt</property> <!-- 函数调用的配置文件 --> </function>
修改函数配置文件,添加dn3 数据节点
[root@mycat1 ~]# vim /usr/local/mycat/conf/partition-hash-int.txt 10000=0 //当sharding_id字段的值是10000时,数据存储在数据节点dn1里 10010=1 //当sharding_id字段的值是10010时,数据存储在数据节点dn2里 10020=2 //当sharding_id字段的值是10020时,数据存储在数据节点dn3里
重启服务
[root@mycat1 conf]# mycat restart
客户端连接分片服务器,存取数据
[root@node10 ~]# mysql -h192.168.1.15 -P8066 -uroot -p123456 mysql> use TESTDB; mysql> create table employee(id int primary key, sharding_id int, name varchar(20), birth_date date);# 存储数据时必须指定字段名列表 mysql> insert into employee-> (id, sharding_id, name, birth_date)-> values-> (1, 10000, 'nb', '2000-01-01'),-> (2, 10010, 'wk', '1998-10-01'),-> (3, 10020, 'plj', '2002-05-04'),-> (4, 10020, 'dmy', '1990-08-02'); Query OK, 4 rows affected (0.21 sec)mysql> select * from employee; +----+-------------+------+------------+ | id | sharding_id | name | birth_date | +----+-------------+------+------------+ | 1 | 10000 | nb | 2000-01-01 | | 2 | 10010 | wk | 1998-10-01 | | 3 | 10020 | plj | 2002-05-04 | | 4 | 10020 | dmy | 1990-08-02 | +----+-------------+------+------------+ 4 rows in set (0.09 sec)
# 分别到3台服务器上查看记录 [root@mysql1 ~]# mysql -uroot -pNSD2021@tedu.cn mysql> use db1; mysql> select * from employee; +----+-------------+------+------------+ | id | sharding_id | name | birth_date | +----+-------------+------+------------+ | 1 | 10000 | nb | 2000-01-01 | +----+-------------+------+------------+ 1 row in set (0.00 sec)[root@mysql2 ~]# mysql -uroot -pNSD2021@tedu.cn mysql> use db2; mysql> select * from employee; +----+-------------+------+------------+ | id | sharding_id | name | birth_date | +----+-------------+------+------------+ | 2 | 10010 | wk | 1998-10-01 | +----+-------------+------+------------+ 1 row in set (0.00 sec)[root@mysql3 ~]# mysql -uroot -pNSD2021@tedu.cn mysql> use db3; mysql> select * from employee; +----+-------------+------+------------+ | id | sharding_id | name | birth_date | +----+-------------+------+------------+ | 3 | 10020 | plj | 2002-05-04 | | 4 | 10020 | dmy | 1990-08-02 | +----+-------------+------+------------+ 2 rows in set (0.00 sec)
2)求模法
概述
使用mod-long规则
切分规则根据配置中输入的数值n
分片规则将数据分成n份(通常dn节点也为n),从而将数据均匀的分布于各节点上
这种策略可以很好的分散数据库写的压力。比较适合于单点查询的情景
配置
查看配置文件,得知使用mod-long分片规则的表名
[root@mycat1 ~]# vim /usr/local/mycat/conf/schema.xml ... ...<table name="hotnews" primaryKey="ID" dataNode="dn1,dn2,dn3"rule="mod-long" /> ... ...
查看规则文件,得知mod-long分片规则使用的函数
[root@mycat1 ~]# vim /usr/local/mycat/conf/rule.xml <tableRule name="mod-long"><rule><columns>id</columns> <!-- 数据分片字段 --><algorithm>mod-long</algorithm> <!-- 函数名 --></rule></tableRule> <function name="mod-long" class="io.mycat.route.function.PartitionByMod"><!-- how many data nodes --><property name="count">3</property> <!-- 指定求模数字 --> </function>
重启服务
[root@mycat1 ~]# mycat restart Stopping Mycat-server... Stopped Mycat-server. Starting Mycat-server...
客户端连接分片服务器,存取数据
[root@node10 ~]# mysql -h192.168.1.15 -P8066 -uroot -p123456 mysql> use TESTDB; mysql> create table hotnews(id int primary key, title varchar(50), content text); Query OK, 0 rows affected (0.59 sec)mysql> insert into hotnews-> (id, title, content)-> values-> (1, 'python', '讲python了'),-> (2, 'mysql', 'mysql'),-> (3, 'mysql更新', '增加全部sql语法'),-> (4, 'mysql', '基础'); Query OK, 4 rows affected (0.14 sec) Records: 2 Duplicates: 0 Warnings: 0mysql> select * from hotnews; +----+--------------------+-----------------------+ | id | title | content | +----+--------------------+-----------------------+ | 1 | python | 讲python了 | | 4 | mysql | mysql | | 2 | mysql | 基础 | | 3 | mysql更新 | 增加全部sql语法 | +----+--------------------+-----------------------+ 4 rows in set (0.07 sec)# 分别到3台服务器上查看记录 [root@mysql1 ~]# mysql -uroot -pNSD2021@tedu.cn mysql> use db1; mysql> select * from hotnews; +----+-------------------+-----------------------+ | id | title | content | +----+-------------------+-----------------------+ | 3 | mysql更新 | 增加全部sql语法 | +----+-------------------+-----------------------+ 1 row in set (0.00 sec)[root@mysql2 ~]# mysql -uroot -pNSD2021@tedu.cn mysql> use db2; mysql> select * from hotnews; +----+--------------------+-----------------------+ | id | title | content | +----+--------------------+-----------------------+ | 1 | python | 讲python了 | | 4 | mysql | mysql | +----+--------------------+-----------------------+ 2 rows in set (0.00 sec)[root@mysql3 ~]# mysql -uroot -p'NSD2021@tedu.cn' mysql> use db3; mysql> select * from hotnews; +----+-------------------+-------------------+ | id | title | content | +----+-------------------+-------------------+ | 2 | mysql | 基础 | +----+-------------------+-------------------+ 1 row in set (0.00 sec)
3)全局表
概述
类型为global的表存储在所有的库中
配置
查看全局表
[root@mycat1 ~]# grep goods /usr/local/mycat/conf/schema.xml<table name="goods" primaryKey="ID" type="global" dataNode="dn1,dn2,dn3" />
客户端连接分片服务器,存取数据
[root@node10 ~]# mysql -h192.168.1.15 -P8066 -uroot -p123456 mysql> use TESTDB; mysql> create table goods(id int primary key auto_increment, name varchar(10)); Query OK, 0 rows affected (0.61 sec)mysql> insert into goods(id, name)-> values-> (1, '奶茶'),-> (2, '矿泉水'),-> (3, '花生'),-> (4, '瓜子'); Query OK, 4 rows affected (0.16 sec) Records: 4 Duplicates: 0 Warnings: 0mysql> select * from goods; +----+-----------+ | id | name | +----+-----------+ | 1 | 奶茶 | | 2 | 矿泉水 | | 3 | 花生 | | 4 | 瓜子 | +----+-----------+ 4 rows in set (0.01 sec)
# 分别到3台服务器上查看记录 [root@mysql1 ~]# mysql -uroot -pNSD2021@tedu.cn mysql> use db1; mysql> select * from goods; +----+-----------+ | id | name | +----+-----------+ | 1 | 奶茶 | | 2 | 矿泉水 | | 3 | 花生 | | 4 | 瓜子 | +----+-----------+ 4 rows in set (0.00 sec)[root@mysql2 ~]# mysql -uroot -pNSD2021@tedu.cn mysql> use db2; mysql> select * from goods; +----+-----------+ | id | name | +----+-----------+ | 1 | 奶茶 | | 2 | 矿泉水 | | 3 | 花生 | | 4 | 瓜子 | +----+-----------+ 4 rows in set (0.00 sec)[root@mysql3 ~]# mysql -uroot -pNSD2021@tedu.cn mysql> use db3 mysql> select * from goods; +----+-----------+ | id | name | +----+-----------+ | 1 | 奶茶 | | 2 | 矿泉水 | | 3 | 花生 | | 4 | 瓜子 | +----+-----------+ 4 rows in set (0.00 sec)
Mysql分库分表(Mycat)相关推荐
- Mysql 分库分表 Mycat
0 课程视频 https://www.bilibili.com/video/BV1Kr4y1i7ru?p=163&spm_id_from=pageDriver&vd_source=ff ...
- MySQL分库分表 mycat
Top NSD DBA2 DAY06 案例1:搭建mycat 分片服务器 1 案例1:搭建mycat 分片服务器 1.1 问题 数据库主机 192.168.4.55 使用db1库存储数据 数据库主机 ...
- mysql 分库分表mycat部署
垂直分割 • 纵向切分 – 把单一的表,拆分成多个表,并分散到不同的数据库 ( 主机 ) 上. – 一个数据库由多个表构成,每个表对应不同的业务, 可以按照业务对表进行分类,将其分布到不同的数据 库 ...
- 高可用Mysql架构_Mysql主从复制、Mysql双主热备、Mysql双主双从、Mysql读写分离(Mycat中间件)、Mysql分库分表架构(Mycat中间件)的演变...
[Mysql主从复制] 解决的问题 数据分布:比如一共150台机器,分别往电信.网通.移动各放50台,这样无论在哪个网络访问都很快.其次按照地域,比如国内国外,北方南方,这样地域性访问解决了. 负载均 ...
- MySQL运维(二)MySQL分库分表概念及实战、读取分离详解
MySQL运维(二)MySQL分库分表详解.读取分离详解 1.MySQL分库分表相关概念 1.1 分库分表概念 1.1.1 分库的原因 分库:就是一个数据库分成多个数据库,部署到不同机器. 如果业务量 ...
- 20、MySQL分库分表,原理实战
MySQL分库分表,原理实战 1.MyCAT分布式架构入门及双主架构 1.1 原理 1.2 主从架构 1.3 MyCAT安装 1.4 启动和连接 1.5 配置文件介绍 2.MyCAT读写分离架构 2. ...
- MySQL分库分表原理
分库分表原理 前言 垂直拆分 水平拆分 分库分表后引入的问题 分库分表中间件 前言 在互联网还未崛起的时代,我们的传统应用都有这样一个特点:访问量.数据量都比较小,单库单表都完全可以支撑整个业务.随着 ...
- 【分布式mysql分库分表中间件sharding】
分布式mysql分库分表中间件,sharding领域的一站式解决方案.具备丰富.灵活的路由算法支持,能够方便DBA实现库的水平扩容和降低数据迁移成本.shark采用应用集成架构,放弃通用性,只为换取更 ...
- 最全的MySQL分库分表方案总结
" 面试中我们经常会碰到的关于分库分表的问题!今天就给大家介绍互联网公司常用 MySQL 分库分表方案!希望对大家的面试有所帮助! 数据库瓶颈 不管是 IO 瓶颈,还是 CPU 瓶颈,最终都 ...
- MySQL分库分表和优化
第九阶段模块三 分库分表技术之MyCat 1.海量存储问题 1.1 背景描述 随着互联网的发展,数据的量级也是成指数的增长,从GB到TB到PB.对数据的各种操作也是愈加的困难,传统的关系性数据库已经无 ...
最新文章
- 2021年大数据Kafka(十):kafka生产者数据分发策略
- python_字符串有时可以比较大小哦!
- JQuery IN ACTION读书笔记之一: JQuery选择器
- BOW模型在ANN框架下的解释
- html引入另一个html
- c语言循环嵌套说课,C语言FOR循环说课稿.doc
- Python-Flask实现电影系统管理后台
- 在职场中,如何能够让下属认真完成工作,又不顶撞你?
- 股票基金历史数据下载接口集合
- 仿英雄联盟LOL网页设计作业 HTML CSS游戏官网网页模板 大学生游戏介绍网站毕业设计 DW游戏主题网页模板下载 游戏娱乐网页成品代码 英雄联盟网页作品下载
- Tita绩效宝:2021年的绩效考核(下)- 绩效考核周期设置
- Android 接入融云即时通讯踩坑
- cvtColor()实际操作
- Unity 改变下载资源商店中资源默认路径的方法
- 黑客泄露澳大利亚大量求职者信息,其中包含11家重要公司名单
- (SWAT-6)输入表写入及模型运行
- 模拟飞机票订票系统设计心得
- 校招java实习生基础知识面试题
- this指向,并改变this指向
- java绘制流程图基本元素,java绘制图片
热门文章
- Latex:图片及子图排版
- 2016年科技阅读列表
- 网络公开课资源 ——关注CS/AI/Math
- 鸟哥的Linux私房菜(服务器)- 第二十章、WWW 伺服器
- java.lang.RuntimeException: Unable to start activity ComponentInfo
- JS编程建议——42:用好正则表达式静态值
- 优化SQL Server数据库查询方法
- 怎样将outlook express中的邮件保留在原邮箱
- BigDecimal的使用举例,包括阶乘的相加求法思路
- [SQL SERVER][Memo]篩選索引