分库分表和分布式数据库

什么情况下需要数据库的分库分表,为什么还需要分布式数据库

分库分表

随着互联网业务的快速发展,传统单体数据库面临以下挑战:

  1. 数据量爆炸

    • 单表存储能力有限(如MySQL单表建议不超过2000万行)。
    • 大表导致索引膨胀,查询性能急剧下降(B+树深度增加)。
  2. 高并发压力:数据库往往是系统的性能瓶颈;

    • 单库的读写能力成为瓶颈(如MySQL QPS通常不超过5k);
    • 单表内锁竞争加剧(如行锁、表锁、页锁);
    • 单库的数据库连接数有限
  3. 可用性风险

    • 单点故障可能导致整个系统不可用。
    • 备份与恢复时间随数据量增长而增加。
  4. 成本优化:对于流水表,随着时间增长,旧数据的读写需求几乎没有,那么冷热数据就可以降低成本压力;

典型场景:电商订单表、支付流水表、社交网络动态等高频写入与海量数据场景。

拆分方案

1. 垂直拆分

垂直拆分:按照业务拆分,不同的业务字段,拆分到不同的表;

通常在微服务的架构中,不同的业务之间本身就是相对比较独立的,天然就是业务数据的垂直拆分;通常需要垂直拆分,也就意味着服务的拆分;

2. 水平拆分

垂直拆分:同样的业务由于数据增量大,单表容量有限,此时需要水平拆分,不同的表的数据结构是一致的;

当下的互联网业务体量大,一般在业务初期就需要对数据量有一个预估,提前规划好库表数量、分片键规则;

分片策略

1. 范围分片

Range-based sharding divides data according to a certain range of data. For example, in a database that stores user order information, range sharding can be done according to the order date. Orders within a certain date range are stored in a shard.

范围分片根据数据特定的范围进行分片 比如,一个存储用户订单的数据库,可以根据订单日期进行范围分片,在一个特定范围内的订单存储在特定的分区

2. 哈希分片

Hash sharding determines the shard where the data is stored by performing a hash operation on a certain key attribute of the data (such as user id, order id, etc.)

Hash sharding can make the data distribution relatively even and reduce the problem of hot-spot data, because hash function tries to ensure that the amount of data received by each shard is similar.

哈希分片通过对一个特定的属性进行hash操作,确定数据所处的分片 哈希算法可以使数据分布均匀,减少热点问题,因为hash函数可以尽量保证每个分片的数据相近

3. 业务属性分片

对于ToB业务,可以直接按照企业属性分片,比如企业Id;(钉钉、飞书等)

对于ToC业务,可以按照用户属性userId分片;

基因分片:分片键关联多个业务属性,根据某一个id的基因片段,生成另一个id;如根据userId的某8位,生成该用户的订单id,那么同一个用户的订单就可以路由到同一个分片;

分片技术方案

  1. 客户端方案;在JDBC驱动层完成分片逻辑,轻量级;一般需要接入客户端SDK;
  2. 代理模式:在服务和数据库间加一层代理,由代理路由,执行;业务无侵入;
  3. 云原生方案;

分库分表的设计思路

1. 业务预期数据量

如果是在分库分表的设计初期,需要考虑2件事:

  • 数据量:首先是需要对业务的大致增量有一个预期,对于MySQL单表通常小于2000w的数据量;
  • 并发量:通常数据库往往会成为业务性能的瓶颈,所以还需要对业务的并发量有一个预估;

比如1天500w增量数据,1年就有

50 * 365 = 18.25
亿的数据量;那么2年的数据增量就有差不多40亿,可以冗余预估到50亿;

每张表按照1000w数据量,那么只需要500张表,按照500w的数据量,则需要1000张表;

表的数量又会影响:数据库的并发性能;如果按照1000张表规划,可以取1024张表,分为

32个库 * 32张表
;如果每个库的写入并发量为1000,那么32个库则为32000并发;能够满足绝大多数的需求;

2. 数据路由

对于订单业务,最方便就是根据订单orderId进行

一致性Hash
数据路由;

但是在订单业务中,按照用户id进行搜索的场景也需要考虑;那么有什么设计方案:

  1. 基因算法
    ,每个订单的创建都通过userId中的基因片段拼接到订单id中,保证同一个用户的订单都能够路由到同一张表;
    1. 订单ID = 时间戳(41bit) + 用户ID基因(4位) + 自增序列(19bit)
    2. 分片键 = 
      订单ID中的用户基因片段
       + 
      订单ID
  2. 搜索引擎
    :数据冗余到搜索引擎,来获取用户的所有订单;

3. 数据的冷热分离

随着业务发展,数据并不都是热点数据,比如订单数据,2年以上的订单几乎没有访问量,可以进行冷热分离

热数据保留1年~2年,之后数据迁移到冷库(历史库),冷库数据再超过2年,可以归档到更便宜的存储,甚至是文件;

订单这类业务通常是按照时间查询,那么业务上需要根据这个特性来指定不同的存储来查询;

为什么还需要分布式数据库

企业数据存量大、增量大的解决方案:分库分表和分布式数据库;

分库分表优缺点: