基因法分库分表概述

1,577 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第17天,点击查看活动详情

假设我们有用户表,订单表,需要分库分表。

最初,设计一张中间映射表,即每次用户查询,先查询映射表,映射表记录了用户ID和订单ID的映射关系,得到对应的表或库信息,再去查询表信息。这种方式虽然能解决数据分库分表查询,但是需要多维护一张额外的表,并且查询也比较复杂,多了一次查询。

用户表            订单表
001(uid)         1000001

映射表
10000011 001(uid)

什么是分库基因?

  通过uid分库,假设分为16个库,采用uid%16的方式来进行数据库路由,这里的uid%16,其本质是uid的最后4个bit决定这行数据落在哪个库上,这4个bit,就是分库基因。

关于分库方法,参考理论:

He meant that taking number mod 2^n is equivalent to stripping off all but the n lowest-order *(right-most)* bits of number.

即: 一个数取余2的n次方,那么余数就是这个数的二进制的最后n位数。所有我们可以位操作符把高位清零就可以得到余数.

所以分库分表的数量是2的n次方,那么二进制的n个位数,就是分库的因子。

什么是基因法分库?

基因分库法: 使用基因的思想,从一个维度的信息里,摘取了一个分库基因,其他维度信息里也全会带上,使得所有维度的信息都能通过此分库基因完成分库。

image.png

tid(64位) 使用分布式ID生成60位(如雪花算法) + 分库因子

按照上述方法,可以保证同一个用户的所有订单,都落在同一个库上,可以通过用户uid%4定位库,也可以通过oid%4定位到库

如上图所示

uid=666的用户发布了一条帖子(666的二进制表示为:0000 0010 1001 1010):

  •  使用uid%16分库,决定这行数据要插入到哪个库中
  •  分库基因是uid的最后4个bit,即1010
  •  在生成tid时,先使用一种分布式ID生成算法生成前60bit(上图中绿色部分)
  •  将分库基因加入到tid的最后4个bit(上图中粉色部分)
  •  拼装成最终的64bit帖子tid(上图中蓝色部分)

  这般,保证了同一个用户发布的所有帖子的tid,都落在同一个库上,tid的最后4个bit都相同,于是:

  •  通过uid%16能够定位到库
  •  通过tid%16也能定位到库

  全局唯一ID也可以通过表自增位置和自增范围实现,比如用户ID哈希为 1 的表,自增位置为1,自增范围为 10。