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:订单表根据idrange范围分表
       因为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分片策略

image-20200316001937093

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,随机插入数据,发现均匀的散落到两个库中

posted @   Edmond辉仔  阅读(208)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示