Skip to content

起源

最近在读一本书 ddia,当看到再平衡部分时,感觉很有启发,就写下了这篇文章。

基本需求

再平衡出要出现在分区之中,我们想要了解分区的概念,那就不得不再提到分片与桶的概念,可以理解为逻辑上区分数据隔离的一种方式。如果我们想要做到再平衡,不管是增加节点还是减少节点,那基本需求就是将分片的数据移动,那么就引出了移动数据的基本需求:

  1. 再平衡之后,负载(数据存储,读取和写入请求)应该在集群中的节点之间公平地共享。
  2. 再平衡发生时,数据库应该继续接受读取和写入。
  3. 节点之间只移动必须的数据,以便快速再平衡,并减少网络和磁盘 I/O 负载。

那么我们为了满足第一点我们需要一个好的算法,保证数据平衡,我们为了满足第二点我们需要隔离平衡处理的线程与读取写入线程,我们为了满足第三点我们需要引入元数据的概念。

注意我们这里没有讨论对于分区的索引,比如倒排索引与主键索引的移动,索引一般与分区存储在一起(逻辑概念)。

我们应该怎么做

现有的比较主流的做法,也是推荐的方式就是需要在创建表时需要将分区的数量进行指定,注意这里并不是说不能够自动分区,而是推荐需要这么做,这是为什么呢?在下面我们慢慢探索。

我们来观察一下当固定分区时,我们添加节点会发生什么,比如我们有 20 个分区,分布在 5 个节点上,那每个节点有 4 个固定的分区,当增加节点时,比如 6 个节点再平衡时,只需要将每个节点下将一个分区移动到新节点下,就完成了!听起来是不是很不错,减少节点同理,我们只需要消耗节点间传输的消耗(这也是为什么需要配置内网地址与网卡的原因)。但是这里也有个很麻烦的问题,当你无法预估你的数据量时,你无法判断一个分区多少个。解决方案总是trade off的。

动态分区

那么我们聊一下当你无法预估数据量并且使用动态分区时,我们会遇到什么

动态分区一般分为两种,一种时根据边界动态,一种时根据节点动态,边界动态顾名思义就是通过当前的数量设置一个阈值,当达到比如 5gb 数据时我们就需要多一个分区,但是这里会遇到一个小问题,当我们有 5 个节点时,我们只有一个分区,读写都打到一个节点之上,当然也有处理方法,有些数据库支持预分区,就是同时拥有动态分区与固定分区的特性,这样就可以利用所有的节点了,第二种根据节点动态时另一种方式处理前面所说的问题,所存在的分区数量是固定的,当加入节点时,就会将分区平均分到所有的节点之上,当然支持的数据库较少,这需要一个极其平衡的平衡算法处理数据的存储。

最后

手动平衡一定时最好的方案,自动平衡总是会出现一些奇怪的问题。