【项目】数据库的分库分表

1/31/2022 ProjectDatabase

# 原因

通常项目如果需要应对大数据、高并发时,都会选择对数据库进行分库分表的优化操作。分库是为了应对高并发,分表是为了应对大数据。

以 MySQL 为例,一台 4 核 / 8G / RAID10 的服务器配置下,单个库能够承载的最大并发量是 1000TPS 左右。如果需要承受高并发,在不增加服务器的前提下,就需要对数据进行分库存储。

同样以 MySQL 为例,一张不超过 20 个字段的数据表,最大数据量最好也控制在 1000w 条左右,这样才能保证检索性能有太大的下降。在不提升硬件配置的前提下,我们需要对数据库表进行划分。

# 划分策略

分库分表需要遵循一定的策略才能提高项目的性能问题。

  • 分库

分库的主要目的是为了减少单个库的压力。那么一个库内的数据表显然不能过多,一般的原则是一个库承载 10 个左右的大数据表就很足够了。

  • 分表

分表的主要目的是为了减少单个表的压力。为了提高单个数据项目的检索能力,我们需要设计一种能够迅速找到目标数据行所属的表的策略。

# 实际例子

假设现在存在一个原始数据库。我们按照划分习惯,将其划分成 10 个库, 100 个数据表。这样就是每个库 10 张表,一共 10 个库。实际的个体数据划分,我们一般根据主键决定数据存放的位置。以主键为 user_id 的数据为例,我们将 user_id MOD (库的个数) ,也就是 user_id MOD 10 ,得到库的位置。再将 user_id MOD (表的个数) ,也就是 user_id MOD 100 ,得到数据表的位置。

例如现在出现一条数据, user_id 为 123 ,那么可以算出 123 MOD 10 = 3 , 再计算 123 MOD 100 = 23 ,则可以得到该数据行应该存放在 3 号库 23 号表的位置。

但是这种情况会出现不适用。假如 user_id 为 100 ,得到 0 号库 0 号表。如果需要将其存入 1 号库 0 号表,那么将是不适用的。所以我们需要对划分的两个数进行调整。

原则是:**库数和表数不能存在公约数,也就是两者互质。**这样我们在分配数据的时候,才会尽量均匀。

所以我们可以划分 11 个库, 100 个表。这样再进行计算就不会出现不适用的情况了。

# 登录授权表

如果我们在对登录授权表等一系列需要按照其他字段划分的数据进行操作,比如按照 user_name 字段进行分库分表,那么我们可以将 user_name 字段进行 hash 操作,将得到的结果再去 MOD 库/表的数量即可。

例如 user_name 的值为 abc ,那么我们需要进行以下的计算:hash(abc) mod 11 mod 100 才能得到最终存放的数据库和数据表。

所以在对项目进行设计的时候,在数据访问层之上还需要设计一个数据路由层,设计适用的逻辑将数据精准命中目标数据库表。

# 总结

在对数据库进行了合理的设计,项目所能承载的最大并发量以及数据量就有了巨大的提升。合理的分库分表,可以使得项目的健壮性得到大幅度的提升。即便是应对亿级用户的登录,也能够轻松以较低的硬件成本实现。

Last Updated: 3/11/2023, 11:25:29 AM