大型电商的订单系统,如何设计分库分表方案?
回答
- 大型电商的订单系统的分库分表,主要考虑的就是分表数量、分表字段、分表算法这几个方面。
1、 分库 vs 分表,怎么理解?
- 分库、分表、分库分表,他是三件事儿,不是一件事儿。
- 分表,是解决单表数据量太大,查询效率慢的问题。
- 分库,是解决并发量太高,数据库连接数不够、数据库的资源性能(内存、CPU、磁盘)不够的问题。
2、分表方式,如何选择?
参考:Java 八股/12-分库分表/分库?分表?分库分表?.md
-
垂直分库:就是把不同的业务的库拆分开。
比如一个电商库,拆分成订单库、库存库、商品库。
-
垂直分表:就是把一张大表,拆分成多张小表。
比如有100个字段,拆分成2张表,每张表各50个字段。
-
水平分库(分表):就是把一个库(表)中包含所有数据,水平的分散到不同的库(表)中。
比如原来单库(表)中有1000万数据,那么我们分成5分,每一份库(表)中就只有200万数据了。
3、分表数量,如何计算?
一个表,拆分成多个表,拆多少张合适呢?
-
公式一、:分表数量 = (订单存量总数 + 预计年增长量 * 保留年限)/2000万 => 向上取最接近的2的幂
比如:存量数据已经有2000万了,预计每年增长500万,我们需要保留10年:
(2000 + 500 * 10) / 2000 = 3.5 => 4 -
公式二、:分库数量 =
分表数量 / 8如果,分表数量本身是小于8的,则 分库数量=分表数量
4、分表字段,如何选择?
建议的两种方案:按照时间分、按照买家 ID 分。
1) 按照时间分表
- 按照时间分表最大的好处:
- 就是简单,逻辑是固定的。
- 按照时间的查询比较快。
- 方便做数据归档以及备份。
- 一般在订单系统中,按照时间分表会做的。也都是把他用来做历史表或者做数据归档。但是,分表这里还是要配合使用业务单号来分。
2) 按照买家 ID 分表
-
一个订单系统中最重要的三个字段:买家 id,卖家 id、订单号。
-
选择买家 ID 的主要原因:避免数据倾斜。
如果,按照卖家 id 分表的话,会有很多大卖家的数据量很大。
那么,他的数据还是会落到单表中,导致这个单表数据量大,查询速度还是很慢。
-
还有两个问题,要解决:
- 按卖家 ID 查询,怎么办?
- 按照订单号查询,怎么办?
-
“问题 1:按卖家 ID 查询,怎么办?”。解决方案:再同步一张卖家表。
基于 binlog 监听买家库的变更,把数据同步到另外一个库(也可能是多库)。
这个库的分表逻辑是按照卖家 id 进行的,在同步的过程中,会基于卖家 id 再重新计算一次分到哪张表中。
注意:
卖家库只做数据同步,不做任何的更新操作。
所有的订单的修改,都基于买家库。即使是卖家的操作也一样。
因为,操作是带订单号的。按订单号操作就行了。
-
“问题 2:按照订单号查询,怎么办?” 。解决方案:采用基因法。
所谓基因法就是:在生成订单号的时候,把分表结果也给他编码到订单号中。
按照订单号查询的时候,解析出这段数字,直接去对应分表查询就好了。
5、分表算法
-
分表算法不需要太精密,太复杂,只需要能实现均分分配就行了。
-
一般就是取模算法。
使用买家 id ,对分表数量取模。