3. 分片策略
分片策略
哈希取模分片:通过表中的某一个字段进行hash算法得到一个哈希值,然后通过取模运算确定数据应该放在哪个分片中,这种方式非常适合随机读写的场景中,它能够很好的将一个大表的数据随机分散到多个小表,前提是哈希算法要设计的好,就是要均衡,如下:
哈希取模运算最大的优点是简单,“先哈希再取模”就好了,最大的缺点是无法适应业务需求的变化,假设根据当前数据表的量以及增长情况,我们把一个大表拆分成了4个小表,看起来满足目前的需求,但是经过一段时间的运行后,发现四个表不够,需要再增加4个表来存储,就是一共需要8个表,这种情况下,就需要对原来的数据进行整体迁移,这个过程非常麻烦。
即一旦目标表或者数据库发生数量上的变化,就会导致所有数据都需要进行迁移,为了减少这种大规模的数据影响,所以引入了一致性hash算法,这也是现实开发中更常见的一种做法。
一致性哈希算法:
将整个哈希值空间组织成一个虚拟的圆环,如假设某哈希函数的值空间为 0 ~ 2^ 32 -1 ,就是我们通过 0 ~ 2^ 32 -1 的数字组成一个虚拟的圆环,圆环的正上方的点代表0,0点右侧的第一个点代表1,以此类推,2、3、4、5、6……直到2^ 32 -1,也就是说0点左侧的第一个点代表2^ 32
-1。我们把这个由2的32次方个点组成的圆环称为hash环。
假设现在水平分表出四个表,table_1、table_2、table_3、table_4,在一致性hash算法中,取模运算不是直接对这四个表来完成,而是对2^ 32来实现。
hash(table编号)%2^ 32 通过上述公式算出的结果一定是一个0到2^ 32-1之间的一个整数,然后在这个数对应的位置标注目标表,四个表通过hash取模之后分别落在hash环的某个位置上,如下:

当添加一条数据时,同样通过hash和hash环取模运算得到一个目标值,然后根据目标值所在的hash环的位置顺时针查找最近的一个目标表,把数据存储到这个目标表中即可,所以,哈希环的作用也是帮助我们确定某条记录最终要插入到哪个表中,需要到哪个表中找到某条记录,如下:
一致性哈希运算不是直接面向目标表,而是面向hash环,这样的好处就是当需要删除某张表或者增加表的时候,对于整个数据变化的影响是局部的,而不是全局。即插入和删除一个表,只会影响后面那个表。增加一个表,只需要将一些数据从新表的下一个表的移动到新表就可以了;删除一个表,只需要将删除表里面的数据移动到下一个表里就可以了。
理论上,各个表表是能够均衡的分布在整个hash环中,然后每个新插入的记录就是均衡的分布到水平分表的各个表里面,但实际情况如下:

也就是产生了hash环偏斜的现象,这种现象导致的问题就是大量的数据都会保存到同一个表中,导致数据分配极度不均匀,如上图,很多数据会被存入到表table_01中。
解决的办法是把这四个节点分别复制一份出来分散到这个hash环中,这个复制出来的节点叫虚拟节点,根据实际需要可以虚拟出多个节点出来,注意这里是按实际需要来,比如可以给table_02、table_03、table_04各虚拟出一个,也可以给table_02虚拟出三个。
范围分片:
基于数据表的业务特性,按照某种范围拆分,这个范围的有很多含义,比如:
① 时间范围,比如我们按照数据创建时间,按照每一个月保存一个表。基于时间划分还可以用来做冷热数据分离,越早的数据访问频次越少。
② 区域范围,区域一般指的是地理位置,比如一个表里面存储了来自全国各地的数据,如果数据量较大的情况下,可以按照地域来划分多个表。
③ 数据范围,比如根据某个字段的数据区间来进行划分。