关于数据库:分库分表之拆分键设计-京东物流技术团队

40次阅读

共计 2637 个字符,预计需要花费 7 分钟才能阅读完成。

家喻户晓,在事实世界中,每一个资源都有其提供能力的最大下限,当繁多资源达到最大下限后就得让多个资源同时提供其能力来满足应用方的需要。同理,在计算机世界中,繁多数据库资源不能满足应用需要时,咱们也会思考应用多个数据库同时提供服务来满足需要。当应用了多个数据库来提供服务时,最为要害的点是如何让每一个数据库比拟平均的承当压力,而不至于其中的某些数据库压力过大,某些数据库没什么压力。这其中的关键点之一就是拆分键的设计。

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 转载请注明起源

正文完
 0