场景介绍:基于用户中心
user表
其他业务都是基于user表的id,即单key业务
千万级数据需要进行水平切分。
1.范围切分法
优点:扩容简单
不足:自动增长需要是连续的,不同的用户访问频率是不一样的,新用户往往更高,所以负载不均衡。
2.hash切分法(取模)
优点:切分简单,负载是均衡的,主键不需要是连续递增的
缺点:扩容复杂,rehash后数据库需要迁移
根据loginName查找uid的不同方法
1.mapping
结构:row(name,id)
单表保存所有数据。
获取id后再取模找到对应的数据库。
2.cache
结构:map<name,id>
数据保存在缓存中。
获取id后再取模找到对应的数据库。
3.loginName生成uid
通过loginName可以生成64bit的uid,取模入库
需要在系统设计之初就这么设计,还有一个缺点可能生成重复的uid
4.分库基因法
通过uid分库,假设分为16个库,采用uid%16的方式来进行数据库路由,这里的uid%16,其本质是uid的最后4个bit决定这行数据落在哪个库上,这4个bit,就是分库基因。
缺点:只能通过一个key来做基因,如果有多个登录账户类别则做不到。
分库基因法详解:
业务:查询用户的所有帖子、查询帖子详情。
普通水平切分:
根据帖子ID切分则无法一次查询用户的所有帖子;
根据用户ID切分则需要先查帖子所属用户;
如上图所示,uid=666的用户发布了一条帖子(666的二进制表示为:1010011010):
使用uid%16分库,决定这行数据要插入到哪个库中
分库基因是uid的最后4个bit,即1010
在生成tid时,先使用一种分布式ID生成算法生成前60bit(上图中绿色部分)
将分库基因加入到tid的最后4个bit(上图中粉色部分)
拼装成最终的64bit帖子tid(上图中蓝色部分)
这般,保证了同一个用户发布的所有帖子的tid,都落在同一个库上,tid的最后4个bit都相同,于是:
通过uid%16能够定位到库
通过tid%16也能定位到库