数据切分的设计方案

本文详细介绍了MyCat数据库中间件的安装配置过程,包括数据分库分表的实现方式,如垂直切分和水平切分,以及如何通过MyCat进行数据分片规则的配置,如枚举分片和取模分片。

1. 数据的切分实现方式

简单来讲,就是讲存放在一台数据库上的数据分布到多台数据库上,形成了一个分布式数据库,大致我们数据的拆分方式分为两种

1.1. 垂直切分

常用于我们的微服务设计中,不同的业务领域存放不同的表,比如用户模块存放我们用户相关表,外部调用通过服务访问用户模块,用户模块再去访问对应的数据库

跨库来实现我们数据的join连接,就会导致查询性能极大的下降

垂直切分的优缺点

优点

  • 拆分后业务更清晰,规则明确
  • 系统之间耦合降低,便于扩展
  • 数据维护简单

缺点

  • 部分业务表无法join,只能通过接口调用,提升了系统的复杂度
  • 跨库事务处理是个问题(2PC,程序端解决2PC-seata)
  • 垂直切分以后,某些业务数据依旧庞大,依然会存在单体性能瓶颈

1.2. 水平拆分

明确的id查询是通过表的存入规则来进行匹配,如果是范围查询,将数据在两个表都进行查询然后进行业务合并

优点

  • 解决了单库大数据,高并发的问题,实现数据的分布式
  • 拆分规则只要封装好,开发人员不用考虑拆分细节
  • 提升了系统的稳定性和负载能力

缺点

  • 拆分规则不太好抽象
  • 分布式事务一致性不好解决
  • 二次扩展的时候、数据迁移、维护难度都比较大

1.3. 整体方案总结

垂直和水平都要面临的问题(一定是先垂直后水平)

  • 分布式事务问题
  • 跨库join问题
  • 多数据源的问题
  • 拆分合并的问题

针对多数据源的管理问题,主要有两种思路

1、客户端模式:只要需要配置好底层的数据源,然后在程序上直接访问即可

2、中间代理模式:由中间代理管理所有数据源,开发人员完全不用关心底层数据源是什么,在哪里,开发人员不用关系拆分规则

基于这两种模式对应的成熟的三方中间件

  • 中间代理模式:MyCat(相当于一个分布式数据库,而我们的MySQL只是他的一个存储仓库)
  • 客户端模式:sharding-jdbc(统一的数据源,由他管理不同的数据链接)

2. MyCat的整体分析

2.1. MyCat的内部逻辑

  • 逻辑库(Schema)

    将分开的物理库合并的一个逻辑数据库

  • 逻辑表(table)

    逻辑表就是物理表的总和

    只要进行了水平切分就是一个分片表,没有切分的就是非分片表

    通过冗余方式复制到所有分片表所在库的表就叫全局表

  • 分片节点(dataNode)

    数据表被分片到不同的分片数据库上,每个分片表所在的库就叫数据节点

  • 分片主机(dataHost)

    所有分片数据实际存放的物理数据库

  • 分片规则(rule)

    MyCat有很多分片规则,基本够用,自己本身是用Java开发的

  • 全局序列号

    • UUID
    • snow id

2.2. MyCat实现数据分库分表

3. MyCat安装应用

http://www.mycat.org.cn/

在这里插入图片描述这是MyCat的物理结构,MyCat本身是不存储数据的

# 需要提前安装两个数据库:这两个数据库是独立,不能是主从关系
# 0.下载mycat
wget http://dl.mycat.org.cn/1.6.7.3/20190927161129/Mycat-server-1.6.7.3-release-20190927161129-linux.tar.gz
# 1.解压
tar -xvf Mycat-server-1.6.7.3-release-20190927161129-linux.tar.gz
# 2.配置server.xml
cd /usr/local/mycat/mycat/conf
vi server.xml

进入server.xml我们去到底部先看用户权限

<user name="root" defaultAccount="true">
  <property name="password">123456</property>
  <property name="schemas">user_module,cart_module,product_module</property>
</user>

开始配置逻辑库:schema.xml

先配置两个物理主机

        <dataHost name="DB213" maxCon="1000" minCon="10" balance="0"
                          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <writeHost host="M1" url="192.168.0.213:3306" user="gavin"
                                   password="123456">
                </writeHost>
        </dataHost>
        <dataHost name="DB214" maxCon="1000" minCon="10" balance="0"
                          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <writeHost host="M1" url="192.168.0.214:3306" user="gavin"
                                   password="123456">
                </writeHost>
        </dataHost>

配置dataNode的数据节点,这里的database是我们的物理存放数据的数据库名

        <dataNode name="dn213" dataHost="DB213" database="user_213" />
        <dataNode name="dn214" dataHost="DB214" database="user_214" />

配置schema节点,schema节点的name是server.xml里配置逻辑库名,要对应

table节点里配置的name是物理数据库存放的实际表名

<schema name="user_module" checkSQLschema="true" sqlMaxLimit="100">
  <!-- auto sharding by id (long) -->
  <table name="user_info" dataNode="dn213,dn214" rule="auto-sharding-long" />
</schema>

现在去两个物理数据库创建两个库user_213,user_214和两个表user_info

CREATE TABLE `user_info` (
  `id` int(11) DEFAULT NULL,
  `username` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

启动MyCat

# 报错
jvm 1    | Caused by: io.mycat.config.util.ConfigException: Illegal table conf : table [ USER_INFO ] rule function [ rang-long ] partition size : 3 > table datanode size : 2, please make sure table datanode size = function partition size

# 根据分片规则去找具体的分片策略
vi rule.xml
# 找到这个规则 auto-sharding-long
        <tableRule name="auto-sharding-long">
                <rule>
                        <columns>id</columns>
                        <algorithm>rang-long</algorithm>
                </rule>
        </tableRule>
	
        <function name="rang-long"
                class="io.mycat.route.function.AutoPartitionByLong">
                <property name="mapFile">autopartition-long.txt</property>
        </function>

vi autopartition-long.txt
0-2000000=0
2000001-4000000=1
4000001-8000000=2
# K=1000,M=10000
# 需要根据dataNode设置节点数

4. MyCat分库分表配置

4.1. server.xml

MyCat用户名,密码,权限,Schema关系

如果一个用户下右多个Schema就以csv格式来写入

多个schema就需要在schema.xml里配置多个组schema

mysql -umycat -p -h192.168.0.211 -P8066

4.2. schema.xml

  • 配置dataHost,包括写host和读host
  • 配置dataNode,指定具体的数据库
  • 配置schema,表名,数据节点,分片规则

dataHost节点

<dataHost name="DB214" maxCon="1000" minCon="10" balance="0"
                          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
# name:主机名,自己命名即可
# maxCon:最大连接
# minCon:最小链接
# balance:负载均衡策略,值有4个
# 1. balance="0",不开启读写分离,所有的操作都在writeHost上操作
# 2. balance="1",全部的readHost与stand by writeHost参与select数据的负载均衡
# 3. balance="2" 所有的读操作会随机writeHost和readHost
# 4. balance="3" 所有的读操作都会随机分发到readHost,writeHost不参与读操作
双主也需要我们自己进行replica,mycat平时只写入一个主机
# writeType 写数据类型
# 1. writeType="0",所有写操作都会发送到配置的第一个writeHost,如果第一个挂了就会自动切到第二个writeHost配置上
# writeType="1",所有的写操作会随机到writeHost上,1.5版本后不推荐
# switchType 切换类型配套我我们的writeType来进行操作的
# -1 表示写操作不自动进行切换
# 1 默认值,自动切换,从第一个到第二个writeHost
# 2 基于MySQL的主从同步的状态决定是否切换

dataNode节点

<dataNode name="dn213" dataHost="DB213" database="user_213" />
# name:节点名
# dataHost:对应dataHost的名字
# database:是物理数据库的保存名称

schema节点

<schema name="user_module" checkSQLschema="true" sqlMaxLimit="100">
		<table name="user_info" dataNode="dn213,dn214" rule="auto-sharding-long" />
</schema>
# name:在server配置里定义的逻辑库名
# checkSQLschema:如果是true会自动去掉数据库前缀
# sqlMaxLimit:为了减轻数据库压力,做的输出限制,默认限制100行
# sqlMaxLimit仅对分片表有效
# table name:物流表名
# rule就是分片规则

4.3. schema相关操作

看下启动命令

Usage: ./mycat { console | start | stop | restart | status | dump }

修改完配置后不需要重启mycat就能使用?

# 更改一些基本配置可以使用脚本操作
# 比如更改了limit就可以使用
reload @@config;
# 比如更新了数据源就需要通过config_all来进行操作了,但这里是更新所有配置,比较慢
reload @@config_all;
  • 模拟一个读写分离的操作
        <dataHost name="DB213" maxCon="1000" minCon="10" balance="2"
                          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="M1" url="192.168.0.213:3306" user="gavin"
                                   password="123456">
                   <readHost host="S1" url="192.168.0.211:3306" user="gavin" password="123456"/>
                </writeHost>
                <!-- <writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/> -->
        </dataHost>
  • 做一个双主的写操作配置
        <dataHost name="DB213" maxCon="1000" minCon="10" balance="1"
                          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <!-- can have multi write hosts -->
                <writeHost host="M1" url="192.168.0.213:3306" user="gavin"
                                   password="123456">
                </writeHost>
                <writeHost host="M2" url="192.168.0.211:3306" user="gavin" password="123456"/> 
        </dataHost>

作业1:自己配置两个双主的writeHost,每个writeHost上挂载一个readHost

5. MyCat的分片规则

5.1. 枚举分片

# columns对应我们的分片列名
				<tableRule name="sharding-by-intfile">
                <rule>
                        <columns>type</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>
                <property name="defaultNode">0</property>
        </function>
        
# 枚举规则
vi partition-hash-int.txt
10000=0
10010=0
10020=0
10001=1
10011=1
10021=1
DEFAULT_NODE=0
# 修改schema
        <schema name="user_module" checkSQLschema="true" sqlMaxLimit="100">
                <!-- auto sharding by id (long) -->
                <table name="user_info" dataNode="dn213,dn214" rule="sharding-by-intfile" />

5.2. 取模分片

# 拿id做取模分片
				<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">2</property>
        </function>
# 修改schema文件
        <schema name="user_module" checkSQLschema="true" sqlMaxLimit="100">
                <!-- auto sharding by id (long) -->
                <table name="user_info" dataNode="dn213,dn214" rule="mod-long" />
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值