mysql10--MyCat实现分库分表
1 分库分表介绍
# 数据切分(sharding)的两种模式
-垂直(纵向)拆分:
垂直分库:按照不同的表(或者Schema)来切分到不同的数据库(主机)之上
垂直分表:将一个表按照字段分成多表,每个表存储其中一部分字段,就是一对一的关系
-水平(横向)拆分:
水平分库:根据表中数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库(主机)中
水平分表:根据表中数据的逻辑关系,将同一个表的数据(按数据行)拆分到多个表中(同一个数据库中)
# 传统分库分表设计方案: 水平分库分表
# 1.range范围:根据一定的范围,存放在不同的表
eg: id=0-1000放到0表中,id=1001-2000的放到1表中
# 2.hash取模:指定的路由key(如:id)对分表总数进行取模
eg: id=12的订单,对2取模得到为0,就会放到0表中
id=13的订单,对2取模得到为1,就会放到1表中
# 热点问题:主要是指 分库分表后,某个分表进行读写操作次数,远高于其他分表,形成热点/焦点问题
eg:订单表根据id的range范围分表
因为id的值会一直递增变大,那这段时间的订单会一直在某一张表中
如id=1000万 ~ id=2000万之间,就导致操作订单表时,全在操作该分表
该表会过热,压力过大,而其他的表没有什么压力
# 总结:优缺点
hash取模方案:没有热点问题,但扩容迁移数据痛苦
range范围方案:扩容不需要迁移数据,但有热点问题
# 刘sir的分库分表之最优方案
https://www.cnblogs.com/liuqingzheng/p/10755148.html
# 企业读写分离及分库分表方案介绍
Mysql-proxy(oracle) # 已不再开发
Mysql-router(oracle) # 重点关注
Atlas (Qihoo 360) # 轻量级,简单
Atlas-sharding (Qihoo 360)
Cobar(是阿里巴巴(B2B)部门开发) # 已不再更新
Mycat(基于阿里开源的Cobar产品而研发)# MyCat分片-海量数据存储解决方案
TDDL Smart Client的方式(淘宝)
DRDS 阿里云的产品
Oceanus(58同城数据库中间件)
OneProxy(原支付宝首席架构师楼方鑫开发)
vitess(谷歌开发的数据库中间件)
Heisenberg(百度)
TSharding(蘑菇街白辉)
Xx-dbproxy(金山的Kingshard、当当网的sharding-jdbc)
amoeba
2 MyCat实现分库分表
# MyCat介绍
基于Java开发的,实现了MySQL公开的二进制传输协议 (底层mysql客户端与服务端的socket封装)
巧妙地将自己伪装成一个MySQL Server
目前市面上绝大多数 MySQL客户端工具和应用都能兼容
# 简单的说
MyCAT就是一个新颖的数据库中间件产品支持mysql cluster或者mariadb cluster,提供高可用性数据分片集群
可以像使用mysql一样使用mycat,对于开发人员来说根本感觉不到mycat的存在
# MariaDB
MariaDB数据库管理系统是MySQL的一个分支,主要由开源社区在维护,采用GPL授权许可。
开发这个分支的原因之一是:
甲骨文公司收购了MySQL后,有将MySQL闭源的潜在风险,因此社区采用分支的方式来避开这个风险。
# 安装: linux系统上
1.要求jdk1.8以上 # java开发
2.推荐mysql5.6以上 # 企业基本都是5.7 或8.0 注:5.8就被改名为8版本了
3.MyCat安装
2.0 MyCat分片策略

2.1 源码安装JDk与MyCat
##### 源码安装jdk
# 1 下载
官方注册下载 jdk1.8以上
-官方地址:https://www.oracle.com/java/technologies/oracle-java-archive-downloads.html
-账号: 2696671285@qq.com 密码: Oracle123
# 2 解压 到/usr/local/java文件夹下
mkdir /usr/local/java
tar -xzvf jdk-8u201-linux-x64.tar.gz -C /usr/local/java
# 3 配置环境变量 /etc/profile 主要是将 java的bin文件夹,配置到环境变量中
vim /etc/profile
# 前两行是JAVA开发的通用配置
# JAVA_HOME是Java的安装位置
# CLASSPATH是Java导入内置模块寻找文件夹的位置
export JAVA_HOME=/usr/local/java/jdk1.8.0_231
export CLASSPATH=.:${JAVA_HOME}/jre/lib/rt.jar:${JAVA_HOME}/lib/dt.jar:${JAVA_HOME}/lib/tools.jar
export PATH=$PATH:${JAVA_HOME}/bin
# 4 读取并执行文件
source /etc/profile
# 5 检查
java -version
##### 安装MyCat
# 1.下载安装压缩包
下载 Mycat-server-1.4-release-20151019230038-linux.tar.gz
-MyCat的官方网站: http://www.mycat.org.cn/
-下载地址: https://github.com/MyCATApache/Mycat-download
# 2.解压 建议/usr/local/mycat目录
mkdir /usr/local/mycat # 建不建立mycat 取决于压缩包是否带这一层
tar -xzvf Mycat-server-1.4-release-20151019230038-linux.tar.gz -C /usr/local
# 3.mycat命令 进入mycat目录的bin目录
# 启动mycat
./mycat start
# 停止:
./mycat stop
# 支持的命令
console | start | stop | restart | status | dump
# Mycat的默认端口号为:8066
# 查看端口占用情况
netstat -nlp | grep 具体端口号
2.2 MyCat分片配置文件
# Mycat重要配置文件
sever.xml # 综合配置数据库的相关信息 端口、内存占用、创建账号/密码
schema.xml # 对数据库表结构的定义
-schema标签 # 用于定义MyCat实例中的逻辑库 ---- 相当于不分表 Mycat中的库名称
数据库中间件可以被看做是一个或多个数据库集群构成的逻辑库
-Table标签 # 用于定义MyCat实例中的逻辑表 ---- 相当于不分表 Mycat中的表名称
其中的rule参数用于指定分片规则
值为auto-sharding-long的分片规则是按ID值的范围进行分片
分片范围配置文件:autopartition-long.txt
-dataNode标签 # 用于定义MyCat实例中的数据节点,也就是通常说的数据分片节点
-dataHost标签 # 用于定义MyCat实例中的节点主机
在mycat逻辑库中也是作为最底层的标签存在
直接定义了具体的数据库实例、读写分离配置(就是主从复制)、
心跳语句(用于mycat检测连接的主机是否中断,默认就行)
rule.xml # 指定相关算法规则,来实现不同的分片数据库
##### 强调:心酸血泪史
mycat中的逻辑库的名字 最好和 真实库中的名字保持一致 # 不然Navicat双击会显示表不存在的错误
即:
# schema.xml中:
<schema name="db1" ....> # name为逻辑库的名字
<dataNode name="dn1" ... database="db1"/> # database为真实库的名字
# 两者最好保持一致
# sever.xml中: 两个用户中的逻辑库名字也要注意修改
<user name="root" defaultAccount="true">
<property name="schemas">db1</property>
</user>
<user name="user">
<property name="schemas">db1</property>
</user>
3 案例之两种常见水平分表
# 前提:使用docker模拟起多个mysql服务
docker run -di --name=test1_mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
docker run -di --name=test2_mysql -p 3307:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql:5.7
3.1 rang-long算法--按id范围分表
schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100">
<table name="user" primaryKey="id" dataNode="dn1,dn2" rule="auto-sharding-long" autoIncrement="true"></table>
</schema>
<dataNode name="dn1" dataHost="localhost1" database="lqz"/>
<dataNode name="dn2" dataHost="localhost2" database="lqz"/>
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM1" url="jdbc:mysql://101.133.225.166:3306" user="root" password="123456">
</writeHost>
</dataHost>
<dataHost name="localhost2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="jdbc:mysql://101.133.225.166:3307" user="root" password="123456">
</writeHost>
</dataHost>
</mycat:schema>
autopartition-long.txt
# 指定ID分片的范围 = 分片节点的索引号
# range start-end ,data node index
# K=1000, M=10000.
0-500K=0 # 0-50万的数据 在数据分片节点0
500K-1000K=1 # 50-100万的数据 在数据分片节点1
测试
用navicat连接mycat,插入50w以后的数据会落到3306库,50w以上会落到3307库
3.2 murmur算法--按hash分表
schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100">
<table name="user" primaryKey="id" dataNode="dn1,dn2" rule="auto-sharding-long" autoIncrement="true"></table>
<table name="article" primaryKey="id" dataNode="dn1,dn2" rule="sharding-by-murmur" autoIncrement="true"></table>
</schema>
<dataNode name="dn1" dataHost="localhost1" database="lqz"/>
<dataNode name="dn2" dataHost="localhost2" database="lqz"/>
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="jdbc:mysql://101.133.225.166:3306" user="root" password="123456">
</writeHost>
</dataHost>
<dataHost name="localhost2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="jdbc:mysql://101.133.225.166:3307" user="root" password="123456">
</writeHost>
</dataHost>
</mycat:schema>
rule.xml
# 在rule.xml中
# 找到表规则定义--默认分片的表主键是id列 若不是,则需要修改
<tableRule name="sharding-by-murmur">
<rule>
<!-- 默认是根据主键id列 -->
<columns>id</columns>
<algorithm>murmur</algorithm>
</rule>
</tableRule>
# 找到hash分片的murmur算法函数--配置分片的节点数量等
<function name="murmur" class="org.opencloudb.route.function.PartitionByMurmurHash">
<!-- 默认是0 -->
<property name="seed">0</property>
<!-- 要分片的数据库节点数量,必须指定,否则没法分片 -->
<property name="count">3</property>
<!-- 一个实际的数据库节点被映射为这么多的虚拟节点,默认是160倍,也就是虚拟节点数是物理节点数的160倍 -->
<property name="virtualBucketTimes">160</property>
<!-- <property name="weightMapFile">weightMapFile</property>
节点的权重,没有指定权重的节点默认是1。以properties文件的格式填写,
以从0开始到count-1的整数值也就是节点索引为key,以节点权重值为值。所有权重值必须是正整数,否则以1代替
-->
<!-- <property name="bucketMapPath">/etc/mycat/bucketMapPath</property>
用于测试时观察各物理节点与虚拟节点的分布情况,如果指定了这个属性,
会把虚拟节点的murmur hash值与物理节点的映射按行输出到这个文件,没有默认值,
如果不指定,就不会输出任何东西 -->
</function>
测试
用navicat连接mycat,随机插入数据,发现均匀的散落到两个库中
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律