每日 3000万订单,如何分库分表?( 二 )


文章插图
 
随着公司业务的快速发展,公司员工快速增多,一个窗口难以应付员工的打饭需求,因此扩展成 2 个窗口,如下图:

每日 3000万订单,如何分库分表?

文章插图
 
同理,对于数据库来说,存在下面 4 种情况就需要考虑分库分表:
3.1 单库出现性能瓶颈
单库出现性能瓶颈,通常有以下几种情况:
 
数据库服务器磁盘空间不足,但是无法扩容,导致写数据异常; 数据库服务器 CPU 压力过大,无法升配,导致读写性能较慢; 数据库服务器内存不足,无法扩容,导致读写性能瓶颈; 数据库服务器网络带宽不足,无法升配,导致读写性能瓶颈; 数据库服务器连接数过多,无法升配,导致客户端连接等待/超时;
 
如下图,单库已经达到了性能瓶颈,因此需要扩容成 2 个数据库:
每日 3000万订单,如何分库分表?

文章插图
 
3.2 单表出现性能瓶颈
单表出现性能瓶颈,通常是因为单表数据量过大,导致读写性能较慢 。
如下图,order 表已经达到了性能瓶颈,因此需要切分成 2 张表:
每日 3000万订单,如何分库分表?

文章插图
 
3.3 微服务化
因公司架构发展,技术团队需要对服务器进行微服务化,从而分库分表 。如下图展示:
每日 3000万订单,如何分库分表?

文章插图
 
3.4 技术调研
技术部门内部作为一项技术调研,通常会选一些重要性相对较低的业务去摸索和实践,方便后期出现上面 3 种情况能够有技术积累去快速支撑 。
四、切分策略
主流的切分策略有 3 种:Range 范围、hash 切分、映射表 。
4.1 Range 范围
Range 范围是指按某个字段的数据区间来进行切分 。
比如:user 表按照 user_id 的数据范围切分成多张表,每 1000 万条数据存放一张表,切分后的表可以放到同一个数据库,也可以放到不同的数据库,示例图如下:
每日 3000万订单,如何分库分表?

文章插图
 
优点
 
方便扩容,每次数据量达到 range 值就新加一张表,可以通过代码实现自动化扩容;
 
缺点
 
存在写偏移,可能有热点问题;
 
举例
比如用户注册场景:user 表,因为新注册的用户数据都是写新表,通常来说新用户的活跃度高,所以读写流量全部集中在最新的 user 表,因此,新表可能存在热点问题 。
4.2 hash 切分
通过对分表键 key 进行一定的运算(通常有取余、取模运算,比如:key % m,key / m,hash(key)/m 等等),通过运算结果来决定路由的库和表 。目前大多数互联网公司主要采用该方法 。
优点
 
数据分片比较均匀,大大降低热点问题;
 
缺点
 
hash 算法选择不合理,后期扩容可能需要迁移数据; 数据被切分到不同的库和表中,可能存在跨节点查询和分页等问题;
 
举例
比如:user 表信息,根据 user_id 对 10 取余,这样就可以通过 user_id 尾号 hash 到 user_0 到 user_9 10 张表中:
每日 3000万订单,如何分库分表?

文章插图
 
4.3 映射表
映射表其实是 Range 范围 和 hash 切分的混合模式,将分表键和数据库的映射关系记录在一个单独的表(表的形式可以是 数据库表,文件或者配置中心) 。
优点
 
可以灵活设置路由规则;
 
缺点:
 
方案比较复杂; 映射表可能也会随着业务量的增大,同样需要分库分表,带来更多的问题;
 
举例
某社区电商下单场景,因为全国仓库的数量有限,所以分库直接使用了仓编编码-数据库映射表(后期新增加仓库,只要在表中增加映射关系),为了保证履约的时效性,用户下单时,商城端会选择最近的仓库,服务器在映射表中根据仓库编码查询并路由到对应的数据库,最后在库中进行 order 表的操作,交互如下图:
每日 3000万订单,如何分库分表?


推荐阅读