开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第17天,点击查看活动详情
假设我们有用户表,订单表,需要分库分表。
最初,设计一张中间映射表,即每次用户查询,先查询映射表,映射表记录了用户ID和订单ID的映射关系,得到对应的表或库信息,再去查询表信息。这种方式虽然能解决数据分库分表查询,但是需要多维护一张额外的表,并且查询也比较复杂,多了一次查询。
用户表 订单表
001(uid) 1000001
映射表
1000001 库1 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个位数,就是分库的因子。
什么是基因法分库?
基因分库法: 使用基因的思想,从一个维度的信息里,摘取了一个分库基因,其他维度信息里也全会带上,使得所有维度的信息都能通过此分库基因完成分库。
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。