2024-08-04
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://www.skjava.com/mianshi/baodian/detail/7554943130

回答

目前主流的分表策略有三种:

  • Range 拆分
  • Hash 取模拆分
  • Rang 拆分 和 Hash 取模拆分的组合

Range 拆分

Range 拆分也叫做范围分表,即根据某个字段的范围来分表,比如我们将订单表的主键 order_id,按照 0 ~ 500 万500 ~ 1000 万 的梯度来分表,如下:

有时候我们也会根据时间来排序,比把按年维度拆分工单表:

这种拆分的优点是它有利于扩容,比如我们按照时间来拆分,理论上是可以无限的扩容,而且不需要担心已经拆分好的数据。

但是它可能会有热点问题,比如 2024 年的工单表,在 2024 年内,几乎所有的请求都会打在 2024 年这张分表中,而2022、2023 的表几乎是已半归档的方式存在。同时,按照时间来拆分的话,也可能会出现数据倾斜的问题,比如随着业务的扩展,2024年的工单数据肯定比 2023 的数据多得多。

Hash 取模拆分

选定一个 Hash 算法对某个字段(例如 user_idorder_idorder_no等等)进行进行哈希运算得到其 Hash 值,然后利用该 Hash 值取模分表的数量,得到的余数就是具体的分表。例如:假设有10 订单表,order_id12345 的记录需要存储时,对 order_id 进行哈希,然后取模 10,结果为5,则存储在第 6 张表中,如下:

Hash 分表一份非常明显的优势就是他数据分布均匀,能够将数据均匀分布到各个表中,能够有效地避免热点问题,但是它有一个问题就是扩容非常麻烦,如果未来某天,表数据量增长到数据瓶颈了,需要进行扩容操作时,就会很麻烦。

所以,选择 Hash 分表测试时一般建议提前规划好,一次性分够,避免未来需要进行扩容操作。

当然,在实际生产场景中我们是可以灵活运用这两种分表策略,可以量量互相配合,比如 Hash 分表 + 时间,比如 Range 分表 + 时间,又或者 Hash 分表 + Range 分表,等等组合的策略,各位小伙伴们可以根据实际情况来进行组合。

大明哥举一个简单的例子,比如我们开发一个博客系统,用户基数非常大,则我们可以用 Hash 对用户表进行分表,然后对用户的博客按照时间来分表,如下:

扩展

分库分表可以从垂直(纵向)和水平(横向)两个维度进行拆分。

垂直拆分

垂直分库

垂直分裤一般来说都是按照业务维护来进行拆分,其核心理念就是专库专用,即将不同的业务数据分别放入到不同的数据库中。

由于业务刚刚开始,为了赶进度,能够尽快上线,我们一般将所有的业务、功能都冗余在一个单体应用中(如果你老板一上来,不管什么系统就是微服务,赶紧离开,因为他会害死你),但是随着业务的发展,我们需要按照业务类型对数据进行分离,比如将一个单体的电商服务拆分为订单、会员、支付、物流、商品、商家等等服务,不同的服务对应不同的数据库,且不同业务禁止跨库直连,统一采用 API 的方式来获取数据,其实就是微服务化!

垂直分表

垂直分表也垂直分库是存在区别的,它是指将一个表按照列来进行拆分为多个表,每个表包含原表中一部分的列,其主要目的是减少单表的宽度,提高查询效率。

比如,我们有一张 tb_user 表,他有 idnameemailphoneaddress 五个字段,如下

在我们使用过程中发现 idname phone 使用很多,但是 emailaddress 使用很少,这个时候我们就可以对 tb_user 表进行垂直分表,比将其拆分为 tb_user_base tb_user_ext 两张表,如下:

当然垂直分表也不是瞎分的,一般都需要遵循几个原则:

  1. 高频字段和低频字段分离:将访问频率较高的字段和较低的字段分开存储,以提高高频字段的访问效率。
  2. 按照业务逻辑进行拆分:根据业务逻辑,将相关性强的字段放在一个表中,相关性弱的字段放在另一个表中。

虽然,垂直分表在一定程度上能够增加查询效率,但是由于一张表变成了多张表,所以会涉及到事务问题,同时,在某些查询的时候可能会涉及到关联表的查询,这样其实效率可能会更加低。

水平拆分

水平拆分是将一个很大的数据表按照某种规则拆分为多个小表,这些小表的表结构与大表一模一样,且每个小表中的数据只包含大表中的一部分数据。

比如,我们有一张 t_user 表中有 1000 万数据,我们按照某种规则将其拆分为 4 张小表 t_user_1t_user_2t_user_3t_user_4,如下:

水平拆分后,减少了单表的数据量,在一定程度上提高了查询的性能,但是分表后,程序的处理会更加复杂,比如某个查询条件的数据位于多个表中,这就涉及到多个问题,比如分页、排序等问题。同时,如果水平分表的键选择不合适,则会导致数据分布不均匀。

阅读全文