订单表的分库分表方案设计(大数据)

原创文章,转载注明出处

 

一、两种方案分库分表

一般业界,对订单数据的分库分表,笔者了解,有两类思路:按照订单号来切分、按照用户id来切分。

方案一、按照订单号来做hash分散订单数据

把订单号看作是一个字符串,做hash,分散到多个服务器去。

具体到哪个库、哪个表存储数据呢?订单号里面的数字来记录着。

现在的微信红包。它的订单分库分表,是对订单号进行hash计算。不是什么取模、取整数。这样数据是均匀分散的。

然后订单号的末尾3个数,里面是包含了库名称、表名称的。

如果要查询某用户的所有订单呢?

由于是根据订单号来分散数据的。他的订单分散在了多个库、多个表中。

总不能去所有的库,所有的表扫描吧。这样效率很低。

其实按照uid切分订单,一样会遇到查询的问题。比如要查询a订单的信息。分库分表的规则是按照uid,都不知道数据在哪个库,无从查。

后续说明解决思路。

一般使用方案二的比较多,一个用户的所有订单,都在一张表里面,那么做分页展示的时候,就容易。

方案二、按照用户id打散订单数据。

 

以uid来切分数据,有两种思路:

一种是,某个范围的uid订单到哪些库。0到2千万uid,对应的订单数据到a库、a表。2千万到4千万对应的订单到b库。

为什么这种方案用得比较少呢?

容易出现瓶颈吗。某个范围内的用户,下单量比较多,那么造成这个库的压力特别大。其他库却没什么压力。

第二种是,使用uid取模运算。第二种方案业界用得比较多。

一方面、处理简单,程序上做取模运算就好了。

另一方面、使用取模的方式,数据比较均匀分散到多个库去了。不容易出现单个库性能瓶颈。

但是不好处也有:即要扩容的时候,比较麻烦。就需要迁移数据了。

要扩容的时候,为了减少迁移的数据量,一般扩容是以倍数的形式增加。比如原来是8个库,扩容的时候,就要增加到16个库,再次扩容,就增加到32个库。这样迁移的数据量,就小很多了。这个问题不算很大问题,毕竟一次扩容,可以保证比较长的时间,而且使用倍数增加的方式,已经减少了数据迁移量。

 

下面笔者,分析一下按照用户id取模的方式分库分表。

按照用户id作为key来切分订单数据,具体如下:

1、 库名称定位:用户id末尾4位 Mod 32。

Mod表示除以一个数后,取余下的数。比如除以32后,余下8,余数就是8。

代码符号是用%表示:15%4=3。

2、表名称定位:(用户id末尾4位 Dev 32) Mod 32。

Dev表示除以一个数,取结果的整数。比如得到结果是25.6,取整就是25。

代码用/来表示:$get_int = floor(15/4)。15除以4,是一个小数3.75,向下取整就是3。一定是向下取整,向上取整就变成了4了。

按照上面的规则:总共可以表示多少张表呢?32个库*每个库32个表=1024张表。如果想表的数量小,就把32改小一些。

上面是用计算机术语来表示, 下面用通俗的话描述。

 

1、库名称计算

用户id的后4位数,取32的模(取模就是除以这个数后,余多少)。余下的数,是0-31之间。

这样可以表示从0-31之间,总共32个数字。用这个32个数字代表着32个库名称:order_db_0、order_db_2.........................order_db_31

2、表名称计算

最后要存储定到哪个表名里面去呢?

用户id的最后4位数,除以32,取整数。将整数除以32,得到余数,能够表示从0-31之间32个数字,表示表名称。

表名称类似这样:order_tb_1、order_tb_2..........................order_tb_31。一个库里面,总共32个表名称。

比如用户id:19408064,用最后4位数字8064除以32,得到是251.9,取它的整数是251。

接着将251除以32,取余数,余数为27。

为了保持性能,每张表的数据量要控制。单表可以维持在一千万-5千万行的数据。1024*一千万。哇,可以表示很多数据了。

三、思考优点和缺点

优点

订单水平分库分表,为什么要按照用户id来切分呢?

好处:查询指定用户的所有订单,避免了跨库跨表查询。

因为,根据一个用户的id来计算节点,用户的id是规定不变的,那么计算出的值永远是固定的(x库的x表)

那么保存订单的时候,a用户的所有订单,都是在x库x表里面。需要查询a用户所有订单时,就不用进行跨库、跨表去查询了。

缺点

这种方式也不是没有缺点。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zzyxpf.html