分库分表之Mycat应用学习四

news2025/7/5 8:46:49

4 分片策略详解

分片的目标是将大量数据和访问请求均匀分布在多个节点上,通过这种方式提升数
据服务的存储和负载能力。

4.1 Mycat 分片策略详解

总体上分为连续分片和离散分片,还有一种是连续分片和离散分片的结合,例如先
范围后取模。
在这里插入图片描述
比如范围分片(id 或者时间)就是典型的连续分片,单个分区的数量和边界是确定
的。离散分片的分区总数量和边界是确定的,例如对 key 进行哈希运算,或者再取模。
关键词:范围查询、热点数据、扩容
连续分片优点:
1)范围条件查询消耗资源少(不需要汇总数据)
2)扩容无需迁移数据(分片固定)
连续分片缺点:
1)存在数据热点的可能性
2)并发访问能力受限于单一或少量 DataNode(访问集中)
离散分片优点:
1)并发访问能力增强(负载到不同的节点)
2)范围条件查询性能提升(并行计算)
离散分片缺点:
1)数据扩容比较困难,涉及到数据迁移问题
2)数据库连接消耗比较多

4.1.1 连续分片

范围分片(已演示)

<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>
# range start-end ,data node index
# K=1000,M=10000. 0-500M=0
500M-1000M=1
1000M-1500M=2

特点:容易出现冷热数据
按自然月分片
建表语句

CREATE TABLE `sharding_by_month` (
`create_time` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTA
`db_nm` varchar(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT

逻辑表

<schema name="catmall" checkSQLschema="false" sqlMaxLimit="100">
	<table name="sharding_by_month" dataNode="dn1,dn2,dn3" rule="qs-sharding-by-month" />
</schema>

分片规则

<tableRule name="sharding-by-month">
	<rule>
		<columns>create_time</columns>
		<algorithm>qs-partbymonth</algorithm>
	</rule>
</tableRule>

分片算法

<function name="qs-partbymonth" class="io.mycat.route.function.PartitionByMonth">
	<property name="dateFormat">yyyy-MM-dd</property>
	<property name="sBeginDate">2019-10-01</property>
	<property name="sEndDate">2019-12-31</property>
</function>

columns 标识将要分片的表字段,字符串类型,与 dateFormat 格式一致。
algorithm 为分片函数。
dateFormat 为日期字符串格式。
sBeginDate 为开始日期。
sEndDate 为结束日期
注意:节点个数要大于月份的个数
测试语句

INSERT INTO sharding_by_month (create_time,db_nm) VALUES ('2019-10-16', database());
INSERT INTO sharding_by_month (create_time,db_nm) VALUES ('2019-10-27', database());
INSERT INTO sharding_by_month (create_time,db_nm) VALUES ('2019-11-04', database());
INSERT INTO sharding_by_month (create_time,db_nm) VALUES ('2019-11-11', database());
INSERT INTO sharding_by_month (create_time,db_nm) VALUES ('2019-12-25', database());
INSERT INTO sharding_by_month (create_time,db_nm) VALUES ('2019-12-31', database());

另外还有按天分片(可以指定多少天一个分片)、按小时分片

4.1.2 离散分片

枚举分片
将所有可能出现的值列举出来,指定分片。例如:全国 34 个省,要将不同的省的数据存放在不同的节点,可用枚举的方式。
建表语句:

CREATE TABLE `sharding_by_intfile` (
`age` int(11) NOT NULL, `db_nm` varchar(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

逻辑表:

<table name="sharding_by_intfile" dataNode="dn$1-3" rule="qs-sharding-by-intfile" />

分片规则:

<tableRule name="sharding-by-intfile">
	<rule>
		<columns>sharding_id</columns>
		<algorithm>hash-int</algorithm>
	</rule>
</tableRule>

分片算法:

<function name="hash-int" class="org.opencloudb.route.function.PartitionByFileMap">
	<property name="mapFile">partition-hash-int.txt</property>
	<property name="type">0</property>
	<property name="defaultNode">0</property>
</function>

type:默认值为 0,0 表示 Integer,非零表示 String。
PartitionByFileMap.java,通过 map 来实现。
策略文件:partition-hash-int.txt

16=0
17=1
18=2

插入数据测试:

INSERT INTO `sharding_by_intfile` (age,db_nm) VALUES (16, database());
INSERT INTO `sharding_by_intfile` (age,db_nm) VALUES (17, database());
INSERT INTO `sharding_by_intfile` (age,db_nm) VALUES (18, database())

特点:适用于枚举值固定的场景。

一致性哈希
一致性 hash 有效解决了分布式数据的扩容问题。
建表语句:

CREATE TABLE `sharding_by_murmur` (
`id` int(10) DEFAULT NULL, `db_nm` varchar(20) DEFAULT NULL
) ENGINE=InnoDB 

逻辑表

<schema name="test" checkSQLschema="false" sqlMaxLimit="100">
	<table name="sharding_by_murmurhash" primaryKey="id" dataNode="dn$1-3" rule="sharding-by-murmur" />
</schema>

分片规则

<tableRule name="sharding-by-murmur">
	<rule>
		<columns>id</columns>
		<algorithm>qs-murmur</algorithm>
	</rule>
</tableRule>

分片算法

<function name="qs-murmur" class="io.mycat.route.function.PartitionByMurmurHash">
	<property name="seed">0</property>
	<property name="count">3</property>
	<property name="virtualBucketTimes">160</property>
</function>

测试语句

INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (1, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (2, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (3, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (4, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (5, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (6, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (7, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (8, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (9, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (10, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (11, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (12, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (13, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (14, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (15, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (16, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (17,database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (18, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (19, database());
INSERT INTO `sharding_by_murmur` (id,db_nm) VALUES (20, database())

特点:可以一定程度减少数据的迁移。
十进制取模分片(已演示)
根据分片键进行十进制求模运算。

<tableRule name="mod-long">
	<rule>
		<columns>sid</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>

特点:分布均匀,但是迁移工作量比较大
固定分片哈希
这是先求模得到逻辑分片号,再根据逻辑分片号直接映射到物理分片的一种散列算法。
建表语句:

CREATE TABLE `sharding_by_long` (
`id` int(10) DEFAULT NULL,
`db_nm` varchar(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

逻辑表

<schema name="test" checkSQLschema="false" sqlMaxLimit="100">
	<table name="sharding_by_long" dataNode="dn$1-3" rule="qs-sharding-by-long" />
</schema>

分片规则

<tableRule name="qs-sharding-by-long">
	<rule>
		<columns>id</columns>
		<algorithm>qs-sharding-by-long</algorithm>
	</rule>
</tableRule>

平均分成 8 片(%1024 的余数,1024=128*8):

<function name="qs-sharding-by-long" class="io.mycat.route.function.PartitionByLong">
	<property name="partitionCount">8</property>
	<property name="partitionLength">128</property>
</function>
  • partitionCount 为指定分片个数列表。
  • partitionLength 为分片范围列
    在这里插入图片描述
    第二个例子:
    两个数组,分成不均匀的 3 个节点(%1024 的余数,1024=2256+1512):
<function name="qs-sharding-by-long" class="io.mycat.route.function.PartitionByLong">
	<property name="partitionCount">2,1</property>
	<property name="partitionLength">256,512</property>
</function>

3 个节点,对 1024 取模余数的分布
在这里插入图片描述
测试语句

INSERT INTO `sharding_by_long` (id,db_nm) VALUES (222, database());
INSERT INTO `sharding_by_long` (id,db_nm) VALUES (333, database());
INSERT INTO `sharding_by_long` (id,db_nm) VALUES (666, database());

特点:在一定范围内 id 是连续分布的
取模范围分片
逻辑表

<schema name="test" checkSQLschema="false" sqlMaxLimit="100">
	<table name="sharding_by_pattern" primaryKey="id" dataNode="dn$0-10" rule="qs-sharding-by-pattern" />
</schema>

建表语句

CREATE TABLE `sharding_by_pattern` (
`id` varchar(20) DEFAULT NULL, `db_nm` varchar(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=ut

分片规则

<tableRule name="sharding-by-pattern">
	<rule>
		<columns>user_id</columns>
		<algorithm>sharding-by-pattern</algorithm>
	</rule>
</tableRule>

分片算法

<function name="sharding-by-pattern" class=" io.mycat.route.function.PartitionByPattern">
	<property name="patternValue">100</property>
	<property name="defaultNode">0</property>
	<property name="mapFile">partition-pattern.txt</property>
</function>

patternValue 取模基数,这里设置成 100
partition-pattern.txt,一共 3 个节点
id=19%100=19,在 dn1;
id=222%100=22,dn2;
id=371%100=71,dn3

# id partition range start-end ,data node index
###### first host configuration
1-20=0
21-70=1
71-100=2
0-0=0

测试语句

INSERT INTO `sharding_by_pattern` (id,db_nm) VALUES (19, database());
INSERT INTO `sharding_by_pattern` (id,db_nm) VALUES (222, database());
INSERT INTO `sharding_by_pattern` (id,db_nm) VALUES (371, database())

特点:可以调整节点的数据分布
范围取模分片
建表语句

CREATE TABLE `sharding_by_rang_mod` (
`id` bigint(20) DEFAULT NULL, `db_nm` varchar(20) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

逻辑表

<schema name="test" checkSQLschema="false" sqlMaxLimit="100">
	<table name="sharding_by_rang_mod" dataNode="dn$1-3" rule="qs-sharding-by-rang-mod" />
</schema>

分片规则

<tableRule name="qs-sharding-by-rang-mod">
	<rule>
		<columns>id</columns>
		<algorithm>qs-rang-mod</algorithm>
	</rule>
</tableRule>

分片算法

<function name="qs-rang-mod" class="io.mycat.route.function.PartitionByRangeMod">
	<property name="mapFile">partition-range-mod.txt</property>
</function>

partition-range-mod.txt

# range start-end ,data node group size
0-20000=1
20001-40000=2

解读:先范围后取模。Id 在 20000 以内的,全部分布到 dn1。Id 在 20001-40000
的,%2 分布到 dn2,dn3。
插入数据:

INSERT INTO `sharding_by_rang_mod` (id,db_nm) VALUES (666, database());
INSERT INTO `sharding_by_rang_mod` (id,db_nm) VALUES (6667, database());
INSERT INTO `sharding_by_rang_mod` (id,db_nm) VALUES (16666, database());
INSERT INTO `sharding_by_rang_mod` (id,db_nm) VALUES (21111, database());
INSERT INTO `sharding_by_rang_mod` (id,db_nm) VALUES (22222, database());
INSERT INTO `sharding_by_rang_mod` (id,db_nm) VALUES (23333, database());
INSERT INTO `sharding_by_rang_mod` (id,db_nm) VALUES (24444, database());

特点:扩容的时候旧数据无需迁移
其他分片规则
应用指定分片 PartitionDirectBySubString
日期范围哈希 PartitionByRangeDateHash
冷热数据分片 PartitionByHotDate
也 可 以 自 定 义 分 片 规 则 : extends AbstractPartitionAlgorithm implements
RuleAlgorithm。

4.1.3 切分规则的选择

步骤:
1、找到需要切分的大表,和关联的表
2、确定分片字段(尽量使用主键),一般用最频繁使用的查询条件
3、考虑单个分片的存储容量和请求、数据增长(业务特性)、扩容和数据迁移问题
例如:按照什么递增?序号还是日期?主键是否有业务意义?
一般来说,分片数要比当前规划的节点数要大。
总结:根据业务场景,合理地选择分片规则
举例:
老师:3.7 亿的数据怎么分表?我是不是分成 3 台服务器?
1、一年内到达多少?两年内到达多少?(数据的增长速度)?
答:一台设备每秒钟往 3 张表各写入一条数据,一共 4 台设备。每张表一天86400*4=345600 条。每张表一个月 10368000 条。
分析:增长速度均匀,可以用日期切分,每个月分一张表。
2、什么业务?所有的数据都会访问,还是访问新数据为主?
答:访问新数据为主,但是所有的数据都可能会访问到。
3、表结构和表数据是什么样的?一个月消耗多少空间?
答:字段不多,算过了,三年数据量有 3.7 亿,30G。
分析:30G 没必要分库,浪费机器。
4、访问量怎么样?并发压力大么?
答:并发有一点吧
分析:如果并发量不大,不用分库,只需要在单库分表。不用引入 Mycat 中间件了。如果要自动路由的话可以用 Sharding-JDBC,否则就是自己拼装表名。
5、3 张表有没有关联查询之类的操作?
答:没有。
分析:还是拼装表名简单一点。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1346066.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

弱电工程计算机网络系统基础知识

我们周围无时无刻不存在一张网&#xff0c;如电话网、电报网、电视网、计算机网络等&#xff1b;即使我们身体内部也存在许许多多的网络系统&#xff0c;如神经系统、消化系统等。最为典型的代表即计算机网络&#xff0c;它是计算机技术与通信技术两个领域的结合。 计算机网络的…

C语言函数篇——sqrt()函数

sqrt()函数介绍&#xff1a; sqrt()函数是C语言中用于计算一个数的平方根的数学函数。它接受一个浮点数作为参数&#xff0c;并返回该数的平方根。 sqrt()函数的语法&#xff1a; double sqrt(double x); 其中&#xff0c;x是要计算平方根的数。 sqrt()函数的应用案例&#x…

【中小型企业网络实战案例 五】配置可靠性和负载分担

【中小型企业网络实战案例 三】配置DHCP动态分配地址-CSDN博客 【中小型企业网络实战案例 四】配置OSPF动态路由协议 【中小型企业网络实战案例 二】配置网络互连互通-CSDN博客 【中小型企业网络实战案例 一】规划、需求和基本配置_大小企业网络配置实例-CSDN博客 配置VRRP联…

matlab导出高清图片,须经修改后放入latex(例如添加文字说明,matlab画图不易操作)

一、背景 我们在写文章时&#xff0c;使用matlab画图后&#xff0c;如果不需要对图片进行额外修改或调整&#xff0c;例如添加文字说明&#xff0c;即可直接从matlab导出eps格式图片&#xff0c;然后插入到latex使用。 通常latex添加图片&#xff0c;是需要eps格式的。 但很…

matplotlib单变量和双变量可视化

使用seaborn 库的tips数据集&#xff0c;其中包含了某餐厅服务员收集的顾客付小费的相关数据&#xff08;评论区&#xff09; 单变量可视化 直方图 直方图是观察单个变量最常用的方法。这些值是经过"装箱"&#xff08;bin&#xff09;处理的 直方图会将数据分组后绘…

通用定时器PWM波输出原理

1通用PWM波输出原理 总结&#xff1a;PWM波周期或频率由ARR决定&#xff0c;PWM波占空比由CCRx决定 1通用PWM模式 1.1PWM模式1 PWM模式1&#xff1a; 递增&#xff1a;CNT < CCRx&#xff0c;输出有效电平1 CNT > CCRx&#xff0c;输出无效电平0 递减&#xff1a;CNT …

蜕变,我的2023

作者&#xff1a;苍何&#xff0c;前大厂高级 Java 工程师&#xff0c;阿里云专家博主&#xff0c;CSDN 2023 年 实力新星&#xff0c;土木转码&#xff0c;现任部门技术 leader&#xff0c;专注于互联网技术分享&#xff0c;职场经验分享。 &#x1f525;热门文章推荐&#xf…

uniapp中组件库的丰富NumberBox 步进器的用法

目录 基本使用 #步长设置 #限制输入范围 #限制只能输入整数 #禁用 #固定小数位数 #异步变更 #自定义颜色和大小 #自定义 slot API #Props #Events #Slots 基本使用 通过v-model绑定value初始值&#xff0c;此值是双向绑定的&#xff0c;无需在回调中将返回的数值重…

【Linux专区】如何配置新服务器 | 添加普通用户到sudoers | 配置vim | git免账号密码pull push

&#x1f49e;&#x1f49e;欢迎来到 Claffic 的博客&#x1f49e;&#x1f49e; &#x1f449; 专栏&#xff1a;《Linux专区》&#x1f448; &#x1f4ac;前言&#xff1a; 时隔131天&#xff0c;你的好友Claffic重新发文了&#xff01;(✿◕‿◕✿) 上期已经带大家白嫖了阿…

MFC - 给系统菜单(About Dialog)发消息

文章目录 MFC - 给系统菜单(About Dialog)发消息概述笔记resource.h菜单的建立菜单项的处理MSDN上关于系统菜单项值的说法END MFC - 给系统菜单(About Dialog)发消息 概述 做了一个对话框程序, 在系统菜单(在程序上面的标题栏右击)中有"关于"的菜单. 这个是程序框架…

Git:常用命令(一)

取得项目的Git 仓库 从当前目录初始化 1 git init 初始化后&#xff0c;在当前目录下会出现一个名为.git 的目录&#xff0c;所有Git 需要的数据和资源都存放在这个目录中。不过目前&#xff0c;仅仅是按照既有的结构框架初始化好了里边所有的文件和目录&#xff0c;但我们还…

考pmp有用么?

PMP考出来究竟有什么用&#xff0c;这个问题一直是站在边缘的朋友经常思考的问题&#xff0c;其实我想说的是&#xff0c;当能力和经验都充足的时候&#xff0c;可能这单单的一张证书就能有莫大的作用&#xff0c;帮助你实现目前所追求的东西。 当我利用这张证书达到我的目的之…

idea部署javaSE项目(awt+swing项目)_idea导入eclipse的javaSE项目

一.idea打开项目 选择需要部署的项目 二、设置JDK 三、引入数据库驱动包 四、执行sql脚本 四、修改项目的数据库连接 找到数据库连接文件 五.其他系统实现 JavaSwing实现学生选课管理系统 JavaSwing实现学校教务管理系统 JavaSwingsqlserver学生成绩管理系统 JavaSwing用…

开源radishes高仿网易云音乐完整源码,可试听和下载“灰色”歌曲,跨平台的无版权音乐平台

源码介绍 Radishes是项目名称&#xff0c;是由萝卜翻译而来。可以在这里试听和下载“灰色”歌曲&#xff0c;是一个可以跨平台的无版权音乐平台。 萝卜音乐界面和功能参考 windows 网易云音乐界面和 ios 的网易云音乐 安装依赖 cd radishes/ yarn bootstrap 运行项目 web:…

Linux shell编程学习笔记38:history命令

0 前言 使用DOS的朋友&#xff0c;都知道可以在命令行提示符中使用上下光标键来浏览最近执行过的命令&#xff0c;这是基于DOS提供的DosKey命令。 而在Unix和Linux的shell中&#xff0c;我们同样可以使用上下光标键来浏览最近执行过的命令历史纪录&#xff08;history&#x…

YOLOv8改进有效系列目录 | 包含卷积、主干、检测头、注意力机制、Neck上百种创新机制

&#x1f451; YOLOv8改进有效系列目录 &#x1f451; 前言 Hello&#xff0c;各位读者们好 本专栏自开设两个月以来已经更新改进教程60余篇其中包含C2f、主干、检测头、注意力机制、Neck多种结构上创新&#xff0c;也有损失函数和一些细节点上的创新。同时本人一些讲解视频…

基于Python的新闻爬取和推荐系统实践

基于Python的新闻爬取和推荐系统实践 项目概述数据集来源技术栈功能特点普通用户功能管理员功能需求 创新点 项目概述 在这个全功能的新闻爬取和推荐系统项目中&#xff0c;我们致力于构建一个高效、智能的平台&#xff0c;为用户提供个性化的新闻阅读体验。采用了Python语言&…

nodejs+vue+ElementUi摄影预约服务网站系统91f0v

本系统提供给管理员对首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;员工管理&#xff0c;摄影套餐管理&#xff0c;套餐系列管理&#xff0c;客片欣赏管理&#xff0c;摄影预约管理&#xff0c;摄影订单管理&#xff0c;取片通知管理&#xff0c;摄影评价管理&…

计算机操作系统(OS)——P4文件管理

1、初始文件管理 1.1、文件的属性 1&#xff09;文件名&#xff1a;由创建文件的用户决定文件名&#xff0c;主要是为了方便用户找到文件&#xff0c;同一目录下不允许有重名文件。 2&#xff09;标识符&#xff1a;一个系统内的各文件标识符唯一&#xff0c;对用户来说毫无…

stm32 HAL库 4096线ABZ编码器

[TOC]目录 ABZ编码器 4096线 买的是这个 AB相代表计数方向&#xff0c;Z代表过零点 cubemx配置 定时器Encoder 也可以选上DMA 中断 Z相GPIO中断 找一个空闲管脚 打开对应中断 代码 不用DMA int main(void) {short Enc_cnt 0;HAL_TIM_Encoder_Start_IT(&ht…