切换语言为:繁体

为什么分库分表的数量要用2的幂?

  • 爱糖宝
  • 2024-05-27
  • 2077
  • 0
  • 0

一般来说,在很多大厂中,需要做分表的时候,分表的数量都会选择2的幂,比如16、64、128、512、1024等,这么做有什么好处呢?

首先,如果你看过 HashMap 的 hash 算法的话,应该知道,HashMap 的容量其实也是2的幂,这么做的好处在下面的文章中讲过,那就是可以讲取模操作改为更加高效的位运算。

因为,hash % 8 相当于 hash & (8-1),所以对于分8个表,可以使用哈希值与7进行按位与操作,这不仅简化了计算,还提升了性能。

所以,使用2的幂作为分表数量的第一个好处,就是可以将取模算法优化成位运算算法

除了这个好处以外,我们通常分表都是伴随着分库的,比如我们分16个库128张表, 这样如果我们的分表数量和分库数量都是2的幂,那么就可以实现均匀分布。128张表就可以均匀的分到16个库中,每个库中有8张表。

所以,使用2的幂作为分表数量的第二个好处,就是可以使得多张分表在多个库中均匀分配。

当我们在做分库分表的时候,必然要考虑的一个问题那就是二次分表的问题,比如我们根据当前的业务发展,计算出可能需要分4张表就够了,但是随着业务增长,可能认为需要更多表才行,这时候如果我们把新的分表数量定位8张表,那么在做数据迁移的时候,就可以只迁移部分数据。

假设我们最开始将订单表分成了4张表,分别是 order_00、order_01、order_02、order_03,这时候假设我们的分表算法是根据 userId取模。即 userId % 4

order_00:userId % 4 == 0
order_01:userId % 4 == 1
order_02:userId % 4 == 2
order_03:userId % 4 == 3

当数据量增长,需要将表扩展到8个时,需要将算法改为userId % 8 :

新的哈希值计算:

order_00:userId % 8 == 0
order_01:userId % 8 == 1
order_02:userId % 8 == 2
order_03:userId % 8 == 3
order_04:userId % 8 == 4
order_05:userId % 8 == 5
order_06:userId % 8 == 6
order_07:userId % 8 == 7

而在做储量数据迁移的时候,我们只需要重新分配那些原来在表0、1、2、3中,且哈希值满足 userId % 8 >= 4 的数据进行迁移就好了,userId % 8 的结果在0-3范围内的数据其实是不用动的。

从表0迁移到表4:如果 hash % 8 == 4
从表1迁移到表5:如果 hash % 8 == 5
从表2迁移到表6:如果 hash % 8 == 6
从表3迁移到表7:如果 hash % 8 == 7

也就是说,从4张表扩容到8张表其实只需要迁移一半的数据。而如果不是2的幂,比如说从5张表扩容成9张表,那每个原数据都需要重新计算哈希值并重新分配到新的表中。因为扩展后的表数量不是2的幂次,大多数数据都会被重新分配到不同的表中。

所以,使用2的幂作为分表数量的第三个好处,也是最重要的一个好处,那就是在做数据迁移时只需重新计算和迁移一半数据。这种方法不仅降低了系统扩展的复杂性,还减少了扩展过程中对系统性能的影响。

0条评论

您的电子邮件等信息不会被公开,以下所有项均必填

OK! You can skip this field.