关于ShardingSphere内置分片算法及其数据倾斜问题总结

news2024/11/15 19:56:00

ShardingSphere是一款不错的分库分表中间件,并且其内置提供了多种分片算法。但是使用内置的分片算法会造成数据倾斜问题。下面以5.2.0版本的ShardingSphere详细介绍下几种内置分片算法并且分析下数据倾斜问题。

一、ShardingSphere内置分片算法介绍

根据官网描述,ShardingSphere内置提供了多种分片算法,能够满足用户绝大多数业务场景的需要。

按照类型可以划分为自动分片算法、标准分片算法、复合分片算法和 Hint 分片算法。其中,自动分片算法包括:取模分片算法,哈希取模分片算法,基于分片容量的范围分片算法,基于分片边界的范围分片算法,自动时间段分片算法。标准分片算法包括:行表达式分片算法,时间范围分片算法。复合分片算法只有复合行表达式分片算法。Hint 分片算法只有Hint 行表达式分片算法。

下面详细介绍下ShardingSphere内置的几种分片算法。

1、自动分片算法

1.1取模分片算法

 其中,分片数量是分库数量或分表数量。

该算法的实现类是org.apache.shardingsphere.sharding.algorithm.sharding.mod.ModShardingAlgorithm.java。

该算法的实质是根据分片键的值分别对数据库或表得分片数量取模来分片,所以分片键必须是数字或纯数字的字符串。

优点:

       1. 简单方便

        2.算法容易理解

        3.可以方便的算出数据落到哪个库哪个表

缺点:

        1.分片键的值的类型受限,必须是纯数字,不能包括字母等

        2.会造成数据倾斜

1.2哈希取模分片算法

 其中,分片数量是数据库数量或表的数量。

该算法的实现类是org.apache.shardingsphere.sharding.algorithm.sharding.mod.HashModShardingAlgorithm.java。

该算法的本质也是取模,不过是先计算分片键的哈希值,即计算分片值的hashCode的绝对值,然后再根据分片数量来取模。所以该算法允许分片键的值包括数字或字母。

优点:

       1. 简单方便

        2.算法容易理解

        3.分片键的值的类型不受限,支持分片值非纯数字类型

缺点:

        1.不方便的快速算出数据落到哪个库哪个表

        2.会造成数据倾斜

1.3基于分片容量的范围分片算法

其中范围上下界必填,该范围根据分片容量将实数区间分为几个部分,根据分片值在具体哪个区间来确定数据落在具体哪个库表。该算法也要求分片值必须为纯数字类型。

该算法的实现类是org.apache.shardingsphere.sharding.algorithm.sharding.range.VolumeBasedRangeShardingAlgorithm.java。

我们来看下该算法具体是如何进行分片的。我们以四库(db_0、db_1、db_2、db_3)四表(order_0、order_1、order_2、order_3),分片键为order_id,range-lower=10,range-upper=25,sharding-volume=10为例。该算法根据范围下界,范围上届及分片容量将整个(-∞,+∞)区间分成5部分,分别为(-∞,10)、[10,20)、[20,25)、(25,+∞)。其内部通过calculatePartitionRange方法缓存维护一个分区及其范围的Map<Integer, Range<Comparable<?>>>,其中0分区对应(-∞,10),1分区对应[10,20),2分区对应[20,25)、3分区对应(25,+∞)。若此时order_id=22,则库表分别在2分区的范围内,所以该条记录在db_2.order_2。

需要注意的是分区数最好和库数或表数相同。比如将上例改为只有两个分库(db_0、db_1),根据该算法算出该条记录应该在db_2.order_2中,但是没有db_2,此时就会报数据库路由错误。

优点:

       1. 简单方便

        2.算法容易理解

        3.可以方便的算出数据落到哪个库哪个表

缺点:

        1.分片键的值的类型受限,必须是纯数字,不能包括字母等

1.4基于分片边界的范围分片算法

该算法与基于分片容量的范围分片算法有些类似,该算法根据设置的分片的范围边界将实数区间分为几个部分,根据分片值在具体哪个区间来确定数据落在具体哪个库表。该算法也要求分片值必须为纯数字类型。

该算法的实现类是 org.apache.shardingsphere.sharding.algorithm.sharding.range.BoundaryBasedRangeShardingAlgorithm.java。

我们来看下该算法具体是如何进行分片的。我们以两库(db_0、db_1)四表(order_0、order_1、order_2、order_3),分片键为order_id,分库算法的sharding-ranges=8,分表算法的sharding-ranges=1,5,10为例。该算法根据分库的分片的范围边界将整个(-∞,+∞)区间分成两部分,其中0分区对应(-∞,8),1分区对应[8,+∞)。根据分表的分片的范围边界将整个(-∞,+∞)区间分成四部分,其中0分区对应(-∞,1),1分区对应[1,5),2分区对应[5,10),3分区对应[10,+∞)。若此时order_id=22,则在库的一分区,表的三分区范围内,所以该条记录在db_1.order_3。

需要注意的是分区数最好和库数或表数相同。比如将上例改为只有三个分表(order_0、order_1、order_2),根据该算法算出该条记录应该在db_1.order_3中,但是没有order_3,此时就会报路由错误。

优点:

       1. 简单方便

        2.算法容易理解

        3.可以方便的算出数据落到哪个库哪个表

缺点:

        1.分片键的值的类型受限,必须是纯数字,不能包括字母等

1.5自动时间段分片算法

该算法针对时间字段类型作为分片键,与前面算法有些类似,都是划分区间,不过不同的是,该算法是将时间进行划分分片。该算法根据设置的分片的起始时间范围、分片的结束时间范围、单一分片所能承载的最大时间,将整个时间区间分为几个部分,根据分片值在具体哪个时间区间来确定数据落在具体哪个库表。

其中,datetime-lower和datetime-upper可以相等,sharding-seconds不能为0。

该算法的实现类是 org.apache.shardingsphere.sharding.algorithm.sharding.datetime.AutoIntervalShardingAlgorithm.java。

我们来看下该算法具体是如何进行分片的。我们以两库(db_0、db_1)四表(order_0、order_1、order_2、order_3),分片键为order_time,分库算法的datetime-lower=2022-12-21 00 :00:00,datetime-upper=2022-12-21 00 :00:00,sharding-seconds=1。分表算法的datetime-lower=2022-12-21 00:00:00,datetime-upper=2022-12-21 00:00:10,sharding-seconds=5为例。该算法根据分库的配置参数将整个时间区间分成两部分,其中0分区对应(-∞,2022-12-21 00 :00:00],1分区对应(2022-12-21 00 :00:00,+∞)。根据分表的配置参数将整个时间区间分成四部分,其中0分区对应(-∞,2022-12-21 00 :00:00],1分区对应(2022-12-21 00 :00:00,2022-12-21 00 :00:05],2分区对应(2022-12-21 00 :00:05,2022-12-21 00 :00:10],3分区对应(2022-12-21 00 :00:10,+∞)。若此时order_time=2022-12-21 00 :00:06,则在库的一分区,表的二分区范围内,所以该条记录在db_1.order_2。

需要注意的是分区数最好和库数或表数相同。比如将上例改为只有两个分表(order_0、order_1),根据该算法算出该条记录应该在db_1.order_2中,但是没有order_2,此时就会报路由错误。

优点:

       1. 简单方便

        2.算法容易理解

        3.可以方便的算出数据落到哪个库哪个表

缺点:

        1.分片键类型受限,必须时间字段类型

        2.会造成数据倾斜

2、标准分片算法

2.1行表达式分片算法

使用 Groovy 的表达式,提供对 SQL 语句中的 = 和 IN 的分片操作支持,只支持单分片键。 对于简单的分片算法,可以通过简单的配置使用,从而避免繁琐的 Java 代码开发,如: t_user_$->{u_id % 8} 表示 t_user 表根据 u_id 模 8,而分成 8 张表,表名称为 t_user_0 到 t_user_7

该算法的实现类是 org.apache.shardingsphere.sharding.algorithm.sharding.inline.InlineShardingAlgorithm.java。

其核心也是根据分片键的值对分片数量进行取模。

优点:

       1. 简单方便

        2.算法容易理解

        3.可以方便的算出数据落到哪个库哪个表

缺点:

        1.分片键的值的类型受限,必须是纯数字,不能包括字母等

        2.会造成数据倾斜

2.2时间范围分片算法

此算法主动忽视了 datetime-pattern 的时区信息。 这意味着当 datetime-lowerdatetime-upper 和传入的分片键含有时区信息时,不会因为时区不一致而发生时区转换。 当传入的分片键为 java.time.Instant 时存在特例处理,其会携带上系统的时区信息后转化为 datetime-pattern 的字符串格式,再进行下一步分片。

 

 该算法的实现类是 org.apache.shardingsphere.sharding.algorithm.sharding.datetime.IntervalShardingAlgorithm.java

我们来看下该算法具体是如何进行分片的。以四表(order_20221201、order_20221202、order_20221203、order_20221204),分片键为order_time,分表算法的datetime-pattern=yyyy-MM-dd HH:mm:ss,datetime-lower=2022-12-01 00 :00:00,datetime-upper=2022-12-04 00 :00:00,sharding-suffix-pattern=yyyyMMdd,datetime-interval-amount=1为例。若此时order_time=2022-12-03 15:00:00,根据算法计算,后缀为20221203,则该数据落在order_20221203表中。

需要注意的是分区数最好和库数或表数相同。比如将上例改为只有两个分表(order_20221201、order_20221202),根据该算法算出该条记录应该在order_20221203中,但是没有order_20221203表,此时就会报路由错误。

优点:

       1. 简单方便

        2.算法容易理解

        3.适合将某一时间段的数据存储一张表的情况,比如每天数据存储一张表, 或每月或每个季度或每年等数据存储一张表。

缺点:

        1.算法配置较麻烦

        2.分片键类型受限,必须时间字段类型

        3.会造成数据倾斜

3、复合分片算法

3.1复合行表达式分片算法

该算法支持分片键多字段的情况,其中sharding-columns如果只配置一个字段,那么该算法将退化为行表达式分片算法。

该算法的实现类是 org.apache.shardingsphere.sharding.algorithm.sharding.complex.ComplexInlineShardingAlgorithm.java

我们来看下该算法具体是如何进行分片的。以四表(order_00, order_01, order_10, order_11),分片键为type和order_id,分表算法的sharding-columns=type,order_id,algorithm-expression=order_${type % 2}${order_id % 2}为例。若此时type=1, order_id=4,根据算法计算,type % 2=1,order_id % 2 = 0,则该数据落在order_10表中。

优点:

       1. 简单方便

        2.算法容易理解

        3.支持多个分片键

        4.可以方便的算出数据落到哪个库哪个表

缺点:

        1.分片键的值的类型受限,必须是纯数字,不能包括字母等

        2.会造成数据倾斜

4、Hint 分片算法

4.1Hint 行表达式分片算法

该算法和行表达式分片算法很类似,不同的是可以不配置algorithm-expression属性,不配置的话默认是找表名为分片键的值的表。

 该算法的实现类是 org.apache.shardingsphere.sharding.algorithm.sharding.hint.HintInlineShardingAlgorithm.java

优点:

       1. 简单方便

        2.算法容易理解

        3.可以方便的算出数据落到哪个库哪个表

缺点:

        1.分片键的值的类型受限,必须是纯数字,不能包括字母等

        2.会造成数据倾斜

5、自定义类分片算法

通过配置分片策略类型和算法类名,实现自定义扩展。 CLASS_BASED 允许向算法类内传入额外的自定义属性,传入的属性可以通过属性名为 props 的 java.util.Properties 类实例取出。

如果strategy=STANDAR,则自定义算法类需要实现org.apache.shardingsphere.sharding.api.sharding.standard.StandardShardingAlgorithm.java接口;strategy=COMPLEX,则自定义算法类需要实现org.apache.shardingsphere.sharding.api.sharding.complex.ComplexKeysShardingAlgorithm.java接口;strategy=HINT,则自定义算法类需要实现org.apache.shardingsphere.sharding.api.sharding.hint.HintShardingAlgorithm.java接口。

优点:

       1. 可以根据业务情况实现自己的分库分表算法,算法较灵活

       2.分片键的值可以是任意形式

       3.一定程度上可以避免数据倾斜问题

缺点:

        1.需要通过Java类的形式实现分库分表策略,增加编码量

二、ShardingSphere内置分片算法的数据倾斜问题

此处所谓的数据倾斜是指,在通过分片算法后大量数据落在某些库表中,导致另某些库表中只有少量或没有数据,导致数据分布不够均匀。

通过上面关于ShardingSphere内置分片算法的介绍,我们可以根据实际的业务情况选择适合的分片算法。如果希望按时间段分片可以选择自动时间段分片算法或者时间范围分片算法。但是该算法也存在因为某些时间段数据激增,某些时间段数据量很少导致数据倾斜。而以按数据库数或表数取模的算法则会存在永远不会有数据落在某些表中的情况。取模分片算法、哈希取模分片算法的实质就是取模。行表达式分片算法、复合行表达式分片算法、Hint 行表达式分片算法的取模形式的行表达式算法也会存在这个问题。比方说,我们按5库20表进行发分库分表,只有分片键是0或是5的倍数才会落到0库,但是又因为是20表,所以落到0库的数据只会分布在0或5或10或15这4个表中,导致路由到0库的数据永远不会落到除上述4个表的其他16个表中,这严重违背了我们的初衷。

下面是分别以2库3表和5库20表,分片值从0-200对库表数进行取模分片的分库分表演算。

分片值2库3表5库20表
2库3表5库20表
00000
11111
20222
31033
40144
51205
60016
71127
80238
91049
1001010
1112111
1200212
1311313
1402414
1510015
1601116
1712217
1800318
1911419
200200
211011
220122
231233
240044
251105
260216
271027
280138
291249
3000010
3111111
3202212
3310313
3401414
3512015
3600116
3711217
3802318
3910419
400100
411211
420022
431133
440244
451005
460116
471227
480038
491149
5002010
5110111
5201212
5312313
5400414
5511015
5602116
5710217
5801318
5912419
600000
611111
620222
631033
640144
651205
660016
671127
680238
691049
7001010
7112111
7200212
7311313
7402414
7510015
7601116
7712217
7800318
7911419
800200
811011
820122
831233
840044
851105
860216
871027
880138
891249
9000010
9111111
9202212
9310313
9401414
9512015
9600116
9711217
9802318
9910419
1000100
1011211
1020022
1031133
1040244
1051005
1060116
1071227
1080038
1091149
11002010
11110111
11201212
11312313
11400414
11511015
11602116
11710217
11801318
11912419
1200000
1211111
1220222
1231033
1240144
1251205
1260016
1271127
1280238
1291049
13001010
13112111
13200212
13311313
13402414
13510015
13601116
13712217
13800318
13911419
1400200
1411011
1420122
1431233
1440044
1451105
1460216
1471027
1480138
1491249
15000010
15111111
15202212
15310313
15401414
15512015
15600116
15711217
15802318
15910419
1600100
1611211
1620022
1631133
1640244
1651005
1660116
1671227
1680038
1691149
17002010
17110111
17201212
17312313
17400414
17511015
17602116
17710217
17801318
17912419
1800000
1811111
1820222
1831033
1840144
1851205
1860016
1871127
1880238
1891049
19001010
19112111
19200212
19311313
19402414
19510015
19601116
19712217
19800318
19911419
2000200

 个人是不太推荐单纯的根据分片键取模分片算法的,在实际的项目中一直使用的是自定义类分片算法,实质是根据分片键的最后一位数字对数据库数取模,分片键的倒数二三位数字对表数取模。这种方式可以尽量避免数据倾斜问题,不会存在某些库表永远不会有数据的情况。

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

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

相关文章

web前端-javascript-包装类(String,Number,Boolean,基本数据类型调用方法先转换为对象再调换)

包装类 1. 说明 在 JS 中为我们提供了三个包装类&#xff0c;通过这三个包装类可以将基本数据类型的数据转化为对象String() 可以将基本数据类型字符串转换为 String 对象 Number() 可以将基本数据类型的数字转换为 Number 对象 Boolean() 可以将基本数据类型的布尔值转换为 …

【C语言】重要函数atoi的使用

目录 一、atoi函数的介绍 二、atoi函数的使用 三、atoi函数的模拟实现 一、atoi函数的介绍 一个专门将字符串转换为整数的库函数&#xff0c;具体用法如下&#xff1a; 字符串str&#xff0c;将其内容转化为整数&#xff0c;该整数作为int值返回。 二、atoi函数的使用 atoi函…

CentOS7安装apache2并启动

CentOS7安装apache2并启动源码安装启动和停止源码安装 地址&#xff1a;https://downloads.apache.org/httpd/ https://downloads.apache.org/httpd/httpd-2.4.54.tar.gz 参考&#xff1a;https://www.cnblogs.com/xiangqs/p/8663947.html 启动和停止 网上搜到的都是/usr/lo…

linux安装redis

目录 一、准备redis 二、上传redis到linux 三、编译与安装 四、修改配置文件 五、设置开放的服务或端口号或直接关闭防火墙 法1&#xff1a; 法2&#xff1a; 六、验证是否成功 1.直接在linux启动客户端 2.在windows启动redis客户端&#xff0c;连接linux的redis服务…

Java+mysql基于ssm的大学生求职招聘系统

本求职招聘管理系统主要包括系统用户管理模块、企业新闻管理模块、招聘发布会管理、招聘信息管理、登录模块、和退出模块等多个模块。它帮助求职招聘管理实现了信息化、网络化,通过测试,实现了系统设计目标,相比传统的管理模式,本系统合理的利用了求职招聘管理数据资源,有效的减…

Docker方式发布jar文件

在IDEA中将SpringBoot项目打为jar包步骤&#xff1a; 1、打开项目的pom.xml文件&#xff0c;添加或修改packaging标签&#xff0c;如下图&#xff1a; <packaging>jar</packaging> 2、点击右侧maven&#xff0c;展开lifecycle&#xff0c;先clean&#xff0c;然后…

普通人应该怎么赚钱,下班后可在家操作的四个兼职副业分享

大家好&#xff0c;我是蝶衣王的小编 不少朋友发觉&#xff0c;单靠薪水好像已经很难再存下钱了&#xff0c;甚至有时候还不够一个月的开销。实际上&#xff0c;如果你想要提升月收益&#xff0c;你可以选择发展副业。那发展什么副业才能赚钱呢 有小伙伴要问&#xff1a;我要…

使用DevEco Device Tool编译并烧录全部步骤和过程详解

一、前言 我们上一篇讲了 “如何搭建设备开发的环境” ,这一篇继续上一篇提到的BearPi-HM_Nano 源码 我购买的是这款 BearPi开发板,有设备的话更好,没有设备的话,一样可以跟着我们的文章一起学习。 在进行编译烧录前需要先下载BearPi-HM_Nano 源码,我们接着往下看。 二…

【漏洞复现】软件漏洞——栈溢出漏洞复现及其原理详解 一文解明什么是栈溢出漏洞

软件漏洞造成软件漏洞原因:如何预防?软件漏洞常见名词栈溢出漏洞复现前准备造成软件漏洞原因: 本质原因是因为人类目前还没办法在原点上区分数据与代码,说白了就是目前人们还没理解编写安全代码的真正方法。 如何预防? 通过修改自身代码、公共库函数的安全性降低漏洞出现频…

springboot 定时任务基础模板

springboot 如何开启定时任务 基础版本 一、在启动类上面加上 EnableScheduling 即可开启定时 SpringBootApplication EnableAsync EnableScheduling public class ScheduleApplication {public static void main(String[] args) {SpringApplication.run(ScheduleApplicatio…

ios xcode Architectures

各个Architecture参数的含义 Architectures 当前设备环境下支持的指令架构。真机环境下是armV7、arm64。模拟器环境下是X86_64、i386、arm64&#xff08;m1设备&#xff09;。 Build Active Architecture Only 是否只编译当前设备的指令架构。值是YES或者NO。一般Debug环境…

什么是数据管理?看完这篇你一定有收获

如今的大数据成为一切生产经营活动的主要驱动因素。由于每天都会产生大量数据&#xff0c;因此我们需要有更好的数据管理解决方案是理所当然的。任何想要在今天取得成功的企业或企业都需要了解数据管理的内容、原因和方式。 大数据&#xff0c;就其本质而言&#xff0c;需要一…

SI/PI仿真概述:有源高速信号、阻抗、滤波方案分析

SI/PI仿真概述 Signal Integrity与Power integrity是当今高速电子产品系统及PCB设计必须保证的两大因素&#xff0c;SI/PI直接决定系统信号、电源质量从而影响数据的正确传输与系统误码率。如何在设计方案阶段评估及模拟SI/PI&#xff0c;就需要借助专业EDA工具进行仿真分析。…

Vue3基础语法(三)

文章目录认识计算属性案例methods vs computedsetter getterwatch侦听器的基本配置其他方式综合案例认识计算属性 案例 插值语法实现&#xff1a; 以上代码不好维护&#xff0c;多次使用会出现重复代码 methods实现&#xff1a; computed实现案例 methods vs computed sett…

【深度思考】如何优雅的校验参数?

在日常的开发工作中&#xff0c;为了保证落库数据的完整性&#xff0c;参数校验绝对是必不可少的一部分&#xff0c;本篇文章就来讲解下在项目中该如何优雅的校验参数。 假设有一个新增学员的接口&#xff0c;一般第一步我们都会先校验学员信息是否正确&#xff0c;然后才会落…

为什么硬盘在macbook上无法编辑?mac不能往移动硬盘拷东西

为什么硬盘在macbook上无法编辑&#xff1f;如果您只想在Mac上查看NTFS文件&#xff0c;只需将NTFS 外置存储设备连接到mac电脑并查看文件。但要编辑或传输文件&#xff0c;则需要NTFS工具。 NTFS文件格式与Mac不兼容&#xff0c;但许多用户仍然喜欢使用NTFS文件&#xff0c;而…

Xshell及Xftp安装配置实现对Linux的远程登录

为什么要远程登录&#xff1f; Linux服务器是小组共享的 正式上线的项目是运行在公网上的 具体的结构图如下图所示&#xff1a; 准备工作 注意&#xff0c;商业用途的Xshell和Xftp是需要收费的&#xff0c;因此&#xff0c;我们下载免费的个人版本即可。 登录官网&#x…

:沉寂6个月,高薪不再是梦,这一次,我赢了......

前言 六个月对于人的一生来说是极其短暂的&#xff0c;有的人迷迷糊糊、浑浑噩噩的就过去了&#xff0c;有的人让其虚度在游戏中&#xff0c;有的人在不喜欢的岗位上日复一日。 但&#xff0c;总有一部分人会选择用来提升自己、或是探索未知领域掌握新的技能&#xff0c;而我…

Promise难懂?一篇文章让你轻松驾驭

前言 前端js学习中&#xff0c;让大家最难受的就是异步的问题&#xff0c;解决异步、回调地狱等问题时你必须得学会promise&#xff0c;对于多数前端程序员来说promise简直就是噩梦&#xff0c;本篇文章就是从通俗易懂的角度做为切入点&#xff0c;帮助大家轻松掌握promise 异步…

如何使用报表工具FastReport VCL 设计器中的 PDF/A?

Fastreport是目前世界上主流的图表控件&#xff0c;具有超高性价比&#xff0c;以更具成本优势的价格&#xff0c;便能提供功能齐全的报表解决方案&#xff0c;连续三年蝉联全球文档创建组件和库的“ Top 50 Publishers”奖。 慧都科技是Fast Reports在中国区十余年的友好合作…