分库分表之拆分键设计 | 京东物流技术团队

news2024/11/25 23:42:32

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

1 水平、垂直拆分

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

1.1 垂直拆分

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

1.2 水平拆分

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

1.3 常用拆分方法

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

2 拆分键的选取

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

2.1 等值法

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

1)订单表

2)运单表

在订单表中,拆分键order_id与运单表中的拆分键waybill_code值相同,当按订单号查询运单表里的运单信息时,可以直接查询拆分键waybill_code获取订单对应的运单信息。

2.2 索引法

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

1)索引表

例:用户user001在商城上购买了一支笔下单的订单号为10001,商家发货后,物流公司给的运单号是Y0023

2)该用户的订单表、运单表模型如下:

订单表:

运单表:

索引表:

当查询用户(user001)的下单记录时,通过用户编码先查询索引表,查询出user001的所有下单的订单号(10001),再通过订单号查询订单表获取用户的订单信息;同理,根据运单号(Y00232)查询订单信息时,在索引表里先查询到对应的订单号,再根据订单号查询对应的订单信息。

2.3 基因法

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

1)订单表

2)运单表

当通过订单表里的订单号查运单表时,通过订单号的低4位定位到该订单号在运单数据库及表的位置,再直接通过脚本查询出订单号对应的运单信息。

3 拆分键的生成

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

3.1 数据库自增主键

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

3.2 UUID

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

import java.util.UUID;

public class UUIDTest {
    public static void main(String[] args) {
        UUID uuid = UUID.randomUUID();
        System.out.println(uuid.toString());
    }
}

3.3 雪花算法

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

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

4 提升总结

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

作者:京东物流 廖宗雄

来源:京东云开发者社区 自猿其说Tech 转载请注明来源

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

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

相关文章

Andorid广播

以下内容摘自郭霖《第一行代码》第三版 文章目录 一、广播机制简介1.1 广播的类型1.1.1 标准广播1.1.2 有序广播 二、接收系统广播2.1 动态注册监听时间变化2.2 静态注册实现开机启动 三、发送自定义广播3.1 发送标准广播3.2 发送有序广播 一、广播机制简介 1.1 广播的类型 A…

EPS倾斜摄影模型测图

1、打开EPS软件,新建工程。 2、加载倾斜摄影模型。在三维测图--倾斜摄影--加载本地倾斜模型中,加载模型到工作空间。 3、加载后的结果如下: 4、开始绘制房屋。选择编码--进入加线模式--开始绘图。 开始绘图图形, 5、绘图按键使用 …

面试题大揭秘!Java中== 与equals的区别?

大家好,我是你们的小米!今天我们要来聊一个在Java面试中经常被问到的问题: 与 equals 的区别。这可是一个重要而且常常令人头疼的问题哦!废话不多说,咱们马上开启今天的探索之旅吧! 背景知识 在开始深入探…

什么是雨量气象站?

过多的强降水会造成重大自然灾害,给我们的生活带来很大影响,实时监测降雨信息,能够及时发布气象预警,防范可能因强降水引起的山洪、泥石流等自然灾害,保护人民群众生命财产安全,提高防灾减灾能力。 雨量气…

【三维重建】【深度学习】NeuS代码Pytorch实现--测试阶段代码解析(下)

【三维重建】【深度学习】NeuS代码Pytorch实现–测试阶段代码解析(下) 论文提出了一种新颖的神经表面重建方法,称为NeuS,用于从2D图像输入以高保真度重建对象和场景。在NeuS中建议将曲面表示为有符号距离函数(SDF)的零级集,并开发一种新的体绘…

springboot+vue实现的智慧学校云平台源码

智慧校园源码 智慧班牌云平台源码 系统架构:Javavue2springbootMySQL elmentuiQuartzjpajwt 智慧校园电子班牌云平台是出于校园考勤管理以及班级校园信息展示为目的的管理系统,电子班牌系统主要用于中小学教育的综合管理平台,融合了多媒体技…

SPSS中级统计--卡方独立性检验之n×c表资料

nc资料表检验 nc资料表分类: ①双向无序的RC表资料 ②单向有序的RC表资料 ③双向有序的RC表资料 1、双向无序RC表资料 多个样本率的比较(c2) 例1:比较不同污染地区的动物畸形率是否有差异? H0:不同污染…

Android中使用JT808协议进行车载终端通信的实现和优化

JT808是一种在中国广泛应用的车载终端通信协议,用于车辆与监控中心之间的数据通信。下面是关于Android平台上使用JT808协议进行通信的一般步骤和注意事项: 协议了解:首先,您需要详细了解JT808协议的规范和定义。该协议包含了通信消…

iServer通过服务实例动态化管理MongoDB万级瓦片集应用实践

作者:Carlo 文章目录 数据特点项目难点优化方案先了解“服务实例动态化管理”功能特性“服务实例动态化管理”应用场景优化1:开启服务实例动态化管理优化2:同时设置一个特定服务关闭动态管理持续存活优化3:将服务配置信息存储到Po…

React(8)

千锋学习视频https://www.bilibili.com/video/BV1dP4y1c7qd?p72&spm_id_frompageDriver&vd_sourcef07a5c4baae42e64ab4bebdd9f3cd1b3 1.React 路由 1.1 什么是路由? 路由是根据不同的 url 地址展示不同的内容或页面。 一个针对React而设计的路由解决方案…

python从入门到精通——完整教程

阅读全文点击《python从入门到精通——完整教程》 一、编程入门与进阶提高 Python编程入门 1、Python环境搭建( 下载、安装与版本选择)。 2、如何选择Python编辑器?(IDLE、Notepad、PyCharm、Jupyter…) 3、Pytho…

安装npm和react

下载react 下载node链接 或者: https://nodejs.org/zh-cn/download/ 下载以后重启电脑(刷新环境变量) 或者手工刷新环境变量 检查环境变量 node -v npm -v如果没有问题应该是这两个: 修改镜像源 npm config set registry ht…

基于swing的在线考试系统java jsp线上试卷问答mysql源代码

本项目为前几天收费帮学妹做的一个项目,Java EE JSP项目,在工作环境中基本使用不到,但是很多学校把这个当作编程入门的项目来做,故分享出本项目供初学者参考。 一、项目描述 基于swing的在线考试系统 系统有2权限:管…

第二篇:基础窗口部件 QWidget

基础窗口部件 QWidget QWidget 类是所有用户界面对象的基类,因此被称为基础窗口部件。QWidget 继承自 QObject 类和QPaintDevice 类,其中 QObject 类是所有支持 Qt 对象模型(Qt Object Model)的对象的基类,QPaintDevi…

LTD与杭州商务局系统签订战略合作协议:共同推动商贸企业数字化

LTD将继续发挥“营销SaaS系统场景应用”的优势,为做强做优做大我国数字经济贡献更多力量。 近日,由杭州市商务局指导,杭州市商务发展研究中心(杭州市中小商贸流通企业服务中心)主办,每日商报承办&#xff0…

【Vue3】 Vue-Router路由和路由导航守卫

路由 前后端分离阶段路由单页面富应用阶段前端路由如何做到URL和内容进行映射?URl的hash(哈希)URl的history Vue-Router基本使用1,安装Vue-Router2,新建页面router文件下的index.js,路由,导入页面,导入路由…

一定解决JavaFx运行时Application爆红色问题

文章目录 注意maven项目创建maven javafx项目配置 注意 以下的问题纯粹是因为新建的是普通项目,而不是Java FX项目,如果新建的是Java FX项目,那么idea会自动给你生成相应的需要的pom.xml文件,并且运行也是正常的 maven项目创建…

RPC和HTTP协议

RPC 全称(Remote Procedure Call),它是一种针对跨进程或者跨网络节点的应用之间的远程过程调用协议。 它的核心目标是,让开发人员在进行远程方法调用的时候,就像调用本地方法一样,不需要额外为了完成这个交…

Rspack 创建 vue2/3 项目接入 antdv(rspack.config.js 配置 less 主题)

一、简介 Rspack CLI 官方文档。 rspack.config.js 官方文档。 二、创建 vue 项目 创建项目(文档中还提供了 Rspack 内置 monorepo 框架 Nx 的创建方式,根据需求进行选择) # npm 方式 $ npm create rspacklatest# yarn 方式 $ yarn create…

SSD基本工作原理了解

SSD与RAM的原理有些类似,RAM使用晶体管和电容来表示0或1,晶体管用于将电荷转移到电容器或从电容器中吸取电荷,并且电荷必须每几微秒刷新一次。 而SSD相比于RAM的非易失性来自于其使用的浮栅晶体管。其创造了一个小笼子,不需要外界…