分库分表之Mycat应用学习四

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.mzph.cn/news/588658.shtml

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

相关文章

基于AT89C51单片机可做实物的温度烟雾火灾报警设计

点击链接获取Keil源码与Project Backups仿真图&#xff1a; https://download.csdn.net/download/qq_64505944/88658141?spm1001.2014.3001.5503 C 源码仿真图毕业设计实物制作步骤02 摘要 随着现代家庭用火、用电量的增加&#xff0c;家庭火灾发生的频率越来越高。火灾报警…

快排例题——第k个数

做道简单一点的题巩固一下 基本思路 与上一个整体相似&#xff0c;通过快速排序将长度为n的整数数列变为从小到大的有序数组&#xff0c;在拿出其中第k个数。 题目描述 给定一个长度为 n 的整数数列&#xff0c;以及一个整数 k&#xff0c;请用快速选择算法求出数列从小到大…

浅学lombok

Lombok&#xff08;Project Lombok&#xff09;是一个用于 Java 编程语言的开源库&#xff0c;旨在减少 Java 代码中的冗余和样板代码&#xff0c;提高开发人员的生产力。它通过使用注解来自动生成 Java 类的常见方法和代码&#xff0c;从而使开发人员能够编写更简洁、更具可读…

ColibriSM v1.4.2 已注册– 仿脸书类社交网络PHP源码

ColibriSM&#xff1a;当代社交网络平台的崛起 一、开篇与概述 在信息时代的浪潮中&#xff0c;社交媒体成为了人们日常生活中不可或缺的一部分。ColibriSM&#xff0c;作为一个仿照脸书&#xff08;Facebook&#xff09;、推特&#xff08;Twitter&#xff09;和照片墙&#…

C++的一些知识

一. 语法 move怎么用 https://blog.csdn.net/zhangmiaoping23/article/details/126051520 这个文章讲的很好&#xff0c;其中有一些疑惑的点 (1) 左值引用不能接右值 class T1{int a; }; int main(){T1 t1 T1();T1 && t1_temp T1(); //T1()是一个临时对象&#xf…

WPF 新手指引弹窗

新手指引弹窗介绍 我们在第一次使用某个软件时&#xff0c;通常会有一个“新手指引”教学引导。WPF实现“新手指引”非常方便&#xff0c;且非常有趣。接下来我们就开始制作一个简单的”新手指引”(代码简单易懂&#xff0c;便于移植)&#xff0c;引用到我们的项目中又可添加一…

Windows电脑引导损坏?按照这个教程能修复

前言 Windows系统的引导一般情况下是不会坏的&#xff0c;小伙伴们可以不用担心。发布这个帖子是因为要给接下来的文章做点铺垫。 关注小白很久的小伙伴应该都知道&#xff0c;小白的文章都讲得比较细。而且文章与文章之间的关联度其实还是蛮高的。在文章中&#xff0c;你会遇…

Go语言程序设计-第6章--方法

Go语言程序设计-第6章–方法 对象就是简单的一个值或者变量&#xff0c;并且拥有其方法&#xff0c;而方法是某种特定类型的函数。 6.1 方法的声明 方法的声明和普通函数的声明类似&#xff0c;只是在函数名字前面多了一个参数。这个参数把这个方法绑定到这个参数对应的类型…

【影像组学入门百问】#58---#62

#58-使用PyRadiomics能提取出多少影像组学特征&#xff1f; 当前支持以下特征类别&#xff1a; 第一阶段统计量 基于形状的&#xff08;3D&#xff09; 基于形状的&#xff08;2D&#xff09; 灰度共生矩阵&#xff08;GLCM&#xff09; 灰度共生长度矩阵&#xff08;GLRLM&a…

springboot接口文档

Swagger 在Spring Boot中生成和维护接口文档的一个常用方法是使用Swagger。Swagger是一个开源软件框架,它帮助开发者设计、构建、记录和使用RESTful Web服务。下面是在Spring Boot项目中使用Swagger来创建接口文档的详细步骤:1. 添加Swagger依赖 在你的Spring Boot项目的pom…

Go语言中的包管理工具之Go Path的使用

GoLang 中常用的包管理的方式 1 &#xff09;概述 常用的有三种 Go PathGo VendorGo Modules 2 &#xff09;发展历程 早期go的包管理存在很大缺陷&#xff0c;甚至可以说没有官方统一的包管理工具 一方面官方在努力发布一些实验性的包管理工具。同时也出现了很多社区开发…

使用uni-app editor富文本组件设置富文本内容及解决@Ready先于onload执行,无法获取后端接口数据的问题

开始使用富文本组件editor时&#xff0c;不知如何调用相关API设置富文本内容和获取内容&#xff0c;本文将举例详解 目录 一.了解editor组件的常用属性及相关API 1.属性常用说明 2.富文本相关API说明 1&#xff09;editorContext 2&#xff09; editorContext.setContents…

JAVA进化史: JDK8特性及说明

JDK 8&#xff08;Java Development Kit 8&#xff09;是Java平台的一个重大版本&#xff0c;于2014年3月发布。该版本引入了许多令人期待的新特性&#xff0c;其中一些改变了Java语言的面貌&#xff0c;提供了更丰富、灵活和现代的编程体验。以下是JDK 8的一些主要特性&#x…

线性投影(linear projection)

1、线性投影介绍 线性投影在数学、统计学、机器学习以及经济学等多个领域都有重要作用&#xff0c;其基本思想是将一个高维空间中的向量或点映射到该空间的某个子空间中。以下是线性投影的一些关键作用 1.1 维度降低&#xff08;Dimensionality Reduction&#xff09;&#xf…

【Leetcode】第 378 场周赛

文章目录 100166. 检查按位或是否存在尾随零题目题意代码 100185. 找出出现至少三次的最长特殊子字符串 I题目思路代码 100184. 找出出现至少三次的最长特殊子字符串 II 100166. 检查按位或是否存在尾随零 题目 题意 这里题目要求的是或运算&#xff0c;所以原数组中只需要有…

LeetCode每日一题.04(不同路径)

一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少条不同的路径&#xff1f; 示例 1…

Spring Cloud + Vue前后端分离-第10章 基于阿里云OSS的文件上传

源代码在GitHub - 629y/course: Spring Cloud Vue前后端分离-在线课程 Spring Cloud Vue前后端分离-第10章 基于阿里云OSS的文件上传 前面介绍的文件上传是基于本地文件服务器的文件上传&#xff0c;但是自己搭文件服务器会有很多运维的问题&#xff0c;比如磁盘满了要扩容…

Spark SQL简介与基本用法

Apache Spark是一个强大的分布式计算框架&#xff0c;Spark SQL是其组件之一&#xff0c;用于处理结构化数据。Spark SQL可以使用SQL查询语言来查询和分析数据&#xff0c;同时还提供了与Spark核心API的无缝集成。本文将深入探讨Spark SQL的基本概念和用法&#xff0c;包括数据…

Flink Job 执行流程

Flink On Yarn 模式 ​ 基于Yarn层面的架构类似 Spark on Yarn模式&#xff0c;都是由Client提交App到RM上面去运行&#xff0c;然后 RM分配第一个container去运行AM&#xff0c;然后由AM去负责资源的监督和管理。需要说明的是&#xff0c;Flink的Yarn模式更加类似Spark on Ya…

Docker构建缓存

Docker镜像的分层结构 Docker的镜像是由一层一层的文件系统组成&#xff0c;以UnionFS&#xff08;联合文件系统&#xff09;堆叠构成Dockerfile中的每个指令都会创建一个新的镜像层镜像层将被缓存和复用当Dockerfile的指令修改了&#xff0c;复制的文件变化了&#xff0c;或者…