当前位置:首页 > 数据库 > 分库分表之拆分键设计

分库分表之拆分键设计

2022年11月08日 20:34:27数据库8

众所周知,在现实世界中,每一个资源都有其提供能力的最大上限,当单一资源达到最大上限后就得让多个资源同时提供其能力来满足使用方的需求。同理,在计算机世界中,单一数据库资源不能满足使用需求时,我们也会考虑使用多个数据库同时提供服务来满足需求。当使用了多个数据库来提供服务时,最为关键的点是如何让每一个数据库比较均匀的承担压力,而不至于其中的某些数据库压力过大,某些数据库没什么压力。这其中的关键点之一就是拆分键的设计。

一、 水平、垂直拆分

在关系数据库中,当单个库的负载、连接数、并发数等达到数据库的最大上限时,就得考虑做数据库和表的拆分。如一个简单的电商数据库,在业务初期,为了快速验证业务模式,把用户、商品、订单都放到一个数据库中,随着业务的发展及用户量的增长,单数据库逐渐不能支撑业务(MySQL中单记录容量超过1K时,单表数据量建议不超过一千万条),这时就得考虑把数据库和表做出拆分。

  • 垂直拆分:简单的说就是将数据库及表由一个拆分为多个,如我们这里的电商数据库,可以垂直拆分为用户数据库、商品数据库和订单数据库,订单表可以垂直拆分为订单基本信息表,订单收货地址表、订单商品表等,每一个表里保存了一个订单的一部分数据。

分库分表之拆分键设计 _ JavaClub全栈架构师技术笔记

  • 水平拆分:简单的说就是将一个库、一个表扩展为多个库,多个表,每一个拆分后的表中保存的依然是一个订单的完整信息。如电商数据库,我们按水平拆分数据库和表后,每一个拆分后的数据库表与现有未拆分前的都保持一致。

分库分表之拆分键设计 _ JavaClub全栈架构师技术笔记

  • 常用拆分方法:上述仅从理论上讲解了可行的水平、垂直拆分方法,在实际的生产上,我们拆分一般是按照水平拆表、垂直拆库这一原则进行,在业务比较复杂的场景下也会对表进行垂直拆分。

分库分表之拆分键设计 _ JavaClub全栈架构师技术笔记

二、 拆分键的选取

分库分表的关键项之一是拆分键的选取,一般情况下,拆分键的选取遵循以什么维度进行查询就选取该维度为拆分键。如:订单表就以订单号作为拆分键,商品表就以商品编号作为拆分键。拆分键选取后,对于一些非拆分键的单条件查询,我们需要怎么支持呢?在这里提供3种方法供参考。

1、 等值法:

对于非拆分键的单条件查询,对这一个单条件的赋值,可以将其值与拆分键保持一致。比如在电商场景中,用户下订单后,需要通过物流给用户把商品送到用户手上。对于用户来说仅能看到订单信息,订单上展示的物流信息用户也是通过订单号查询而来;但对于物流系统来说,其系统里的业务主键(拆分键)是运单号,此时,运单号如果和订单号相同,即可完美解决这一问题。订单表和运单表的基本数据模型如下:

订单表:

拆分键

商品编号

收货地址

Order_id

Sku_code

address

运单表:

拆分键

订单号

重量

Waybill_code

Order_Id

weight

2、 索引法:

对于常用的非拆分键,我们可以将其与拆分键之间建立一个索引关系,当按该条件进行查询时,先查询对应的拆分键,再通过拆分键查询对应的数据信息。订单表的索引法查询表模型如下:

索引表:

非拆分键查询条件

拆分键

用户编码

订单号

运单号

订单号

3、 基因法:

拆分键与非拆分键的单号生成规则中,存在相同规则的部分且该部分被用作拆分键来进行库表的定位。比如:订单号生成时,生成一个Long类型的单号,由于Long是64位的,我们可以用其低4位取模来定位该订单存储的数据库及表,其他的表的拆分键也用Long类型的低4位取模来定位对应的数据库及表。还是用订单表和运单表的模型做解释如下:

订单表:

拆分键

商品编号

收货地址

Order_id

Sku_code

address

运单表:

拆分键

订单号

重量

Waybill_code

Order_Id

weight

当通过订单表里的订单号查运单表时,可以直接用订单号来查询其对应的运单信息。

三、 拆分键的生成

拆分键选取后,接下来是拆分键的生成,拆分键的生成有多种方式,建议根据业务量及并发量的大小来确定拆分键生成的规则,在这里介绍几种常用的拆分键生成规则。

1、 数据库自增主键

在并发量不大的情况下,我们可以使用MySQL数据库里的自增主键来实现拆分键。

2、UUID

在Java里,可以使用Java自带的UUID工具类直接生成,UUID的组成:UUID=当前日期和时间+时钟序列+全局唯一的IEEE机器识别号组成。其中,全局唯一的IEEE机器识别号一般是通过网卡的MAC地址获得,没有网卡时以其他的方式获得。UUID生成的编号不会重复,但不利于阅读和理解。

3、雪花算法

雪花算法生成的ID是一个64位大小的整数,结构如下:

分库分表之拆分键设计 _ JavaClub全栈架构师技术笔记

从其结构可以看出,第一位是符号位,在使用时一般不使用,后面的41位是时间位,是由时间戳来确定的,后面的10位是机器位,最后的12位是生成的ID序列,是每豪秒生成的ID数,即每毫秒可以生成4096个ID。从该结构可以看出,10位机器位决定了使用机器的上限,在某些业务场景下,需要所有的机器使用同一个业务空间,这可能导致机器超限;同时,每一个机器分配后如果机器宕机需要更换时,对ID的回收也需要有相应的策略;最为关键的一点是机器的时间是动态调整的,有可能会出现时间回退几毫秒的情况,如果这个时候获取到这个时间,则会生成重复的ID,导致数据重复。

4、 开源中间件

ID生成的开源中间件比较多,如美团的leaf,百度的Uid-Generator。在此就不做过多的展开,感兴趣的同学可去github获取对应的源码。

Leaf: GitHub - Meituan-Dianping/Leaf: Distributed ID Generate Service 

Uid-Generator: GitHub - baidu/uid-generator: UniqueID generator

四、 提升总结

单数据库不能满足业务场景的情况下,主要的思路还是要进行拆分,无论是NoSQL还是关系数据库,随着业务量的增长,都得需要把多个服务器资源组合成一个整体共同来支撑业务。数据库拆分后,如果业务上有多个复杂查询条件的需求,一般就得把数据同步到NoSQL数据库里,由NoSQL来提供支持。无论什么时候,数据库提供的主要能力是存储能力,对于复杂的计算需求,一般是需要在业务逻辑里实现。

作者:liaozxbj
来源链接:https://blog.csdn.net/liaozxbj/article/details/122689743

版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。


本文链接:https://www.javaclub.cn/database/68611.html

标签: 分库分表
分享给朋友:

“分库分表之拆分键设计” 的相关文章

sharding-jdbc结合mybatis实现分库分表功能

sharding-jdbc结合mybatis实现分库分表功能

  最近忙于项目已经好久几天没写博客了,前2篇文章我给大家介绍了搭建基础springMvc+mybatis的maven工程,这个简单框架已经可以对付一般的小型项目。但是我们实际项目中会碰到很多复杂的场景,比如数据量很大的情况下如何保证性能。今天我就给大家介绍数据库分库分表的优化,本文介...

分库分表下分页查询解决方案

分库分表下分页查询解决方案

分库分表下分页查询解决方案 不管是随着业务量的增大、还是随着用户数量的增长,在单一表中无法承受大量大数据,导致查询速度极慢甚至拖垮数据库。所以分库分表的策略随之应用,但是如何在分库分表的情况下,进行分页查询,目前仍是业界难题。 本文记录了...

通过四道常问面试题,带你了解什么是数据库分库分表

通过四道常问面试题,带你了解什么是数据库分库分表

分布式数据库已经流行好多年,产品非常众多,其中分布式数据库中间件使用场景最广。本文主要是通过几道关于分库分表的常问面试题带你深入了解数据库分库分表,希望对大家能够有所帮助! 编者语:为了避免被误解为:「手里有把锤子,看什么都是钉子!」,说明一下不是什么业务都...

分享一个MySQL分库分表备份脚本(原)

分享一个MySQL分库分表备份脚本(原)

分享一个MySQL分库备份脚本(原) 开发思路: 1.路径:规定备份到什么位置,把路径(先判断是否存在,不存在创建一个目录)先定义好,我的路径:/mysql/backup,每个备份用压缩提升效率,带上时间方便整理 2.取数据库:抓取数据库名称,我用的awk和grep配...

MySQL分表、分库、分片和分区知识

MySQL分表、分库、分片和分区知识

一、前言   数据库的数据量达到一定程度之后,为避免带来系统性能上的瓶颈。需要进行数据的处理,采用的手段是分区、分片、分库、分表。 二、分片(类似分库)   分片是把数据库横向扩展(Scale Out)到多个物理节点上的一种有效的方式,其主要目的是...

MYSQL分库分表和不停机更改表结构

在MYSQL分库分表中我们一般是基于数据量比较大的时间对mysql数据库一种优化的做法,下面我简单的介绍一下mysql分表与分库的简单做法。 1、分库分表 很明显,一个主表(也就是很重要的表,例如用户表)无限制的增长势必严重影响性能,分库与分表是一个很不错的解决途径,也就是...

MySQL高可用机制和分库分表

目录 主从架构 为什么需要主从架构 同步机制实现原理 搭建主从集群 全库同步和部分同步 GTID同步 半同步复制...

【shardingjdbc&Mysql】基于springboot+shardingjdbc+tkmapper实现mysql分库分表

【shardingjdbc&Mysql】基于springboot+shardingjdbc+tkmapper实现mysql分库分表

1.实现原理(核心) 1.分库原则 2.分表原则 3.动态切换数据源 2.实现(配置及依赖就不过多描述了) 注意事项:集成tkmapper分表时,table注解的名字命名,别指定具体表名,而是指定shardingjdbc的logicTa...

mysql分表后的联合查询

前言 在分表完之后显然对于数据的查询会变的比较的复杂,特别是在表的关联方面,在有些情况下根本就不能使用JOIN。 其实个人是比较鼓励将那些大的JOIN SQL拆分成几个小的SQL来查询数据。这样虽然总体的效率可能会稍稍下降(如果使用了连接池完全可以忽略)...

SpringBoot sharding 分库分表使用及配置

SpringBoot sharding 分库分表使用及配置 官方提供配置方式有哪些? JAVA配置 YAML配置 SpringBoot配置 Spring命名空间配置 无论哪种方式最后底层都包装成JAVA代码方式配置,今天主要以SpringBo...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。