(转)【订单号存储】最硬核实用的分库分表操作指南

原文:https://blog.csdn.net/wuhuagu_wuhuaguo/article/details/105166470

原文:https://blog.csdn.net/HD243608836/article/details/103801502

 

两种方案分库分表:按照用户id来切分(推荐)、按照订单号来切分。

方案一、按照用户id打散订单数据(推荐)

(2.1)某个范围的uid订单到哪些库。

0到2千万uid,对应的订单数据到a库、a表。2千万到4千万对应的订单到b库。
---缺:某个范围内的用户,下单量比较多,那么造成这个库的压力特别大。

(2.2)使用uid取模运算(推荐)

库名称计算【用户id末尾4位 mod 32】:对用户id的后4位数对32取模(取模就是除以这个数后,余多少),是0-31之间。32个数字代表着32个库名称:order_db_0、order_db_2...order_db_31。
表名称计算【(用户id末尾4位 dev 32) mod 32】:用户id的最后4位数,除以32,向下取整。将整数除以32,得到余数,能够表示从0-31之间32个数字表示表名称:order_tb_1、order_tb_2...order_tb_31。
比如用户id=19408064,用最后4位数字8064除以32取余=32;用最后4位数字8064除以32,得到是251.9,取它的整数是251,接着将251除以32,取余数,余数为27。所以分到库order_db_32的表order_tb_251。
为了保持性能,每张表的数据量要控制。单表可以维持在1千万-5千万行的数据。32*32=1024,可存储的数据总量=1024*1千万=100亿+!!!
---优点:查询指定用户的所有订单,避免了跨库跨表查询。根据一个用户的id来计算节点是不变的(a用户的所有订单都固定的x库的x表)
---缺1:要扩容的时候需要迁移数据。
---解1:要扩容的时候,为了减少迁移的数据量,一般扩容是以倍数的形式增加。比如原来是8个库,扩容的时候,就要增加到16个库,再次扩容,就增加到32个库。这样迁移的数据量,就小很多了。这个问题不算很大问题,毕竟一次扩容,可以保证比较长的时间,而且使用倍数增加的方式,已经减少了数据迁移量。

---缺2:输入订单号,怎么知道去哪个库、哪个表查询呢?
---解2:只要知道了这个订单号是谁的(得到了用户id),就能知道去哪个库、哪个表查询数据了。
做法:a.建立订单号和用户id的订单用户索引关系表order_user_idx。存储的数据包括两项:订单号、用户编号。
     b.当创建订单的时候,就要把关系插入到表里面去了。保存关系记录时,为了减低用户等待时间,不需要实时,做成异步,加入到消息队列中去操作。
     c.一个订单,在创建的时候就已经分配好给指定用户了,以后不会再变。该表可以放到内存中缓存起来(数据库那张索引关系表也要有,数据要持久化)。查询的时候,先走内存缓存查询。如果查询不到,再走数据库查询一下关系。

---缺3:订单用户索引关系表过大,单表过大咋办?
---解3:订单用户关系索引表也进行分库分表:直接根据订单号取模进行分库分表。麻烦但能解决问题。

---缺4:b2c平台,订单的卖家就一个是平台自己。b2b平台,上面支持开店,买家和卖家都要能够登陆看到自己的订单。
---解4:淘宝的做法是数据冗余:拆分买家库和卖家库,也就是两个库:买家库、卖家库。一个订单,在买家库里面有,在卖家库里面也存储了一份。
做法:a.创建订单的时候,要写两份数据。先把订单写入买家库里面去,然后通过消息中间件来同步订单数据到卖家库里面去。
     b.修改订单的时候,买家库的订单a修改了后,要发异步消息,通知到卖家库去,更改状态。


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

应用:微信红包
做法:对订单号进行hash计算,保证数据均匀分散,订单号的末尾3个数,里面是包含了库名称、表名称的。
---缺:如果要查询买卖用户的所有订单呢?由于是根据订单号来分散数据的,他的订单分散在了多个库多个表中,扫描全部的库表效率很低。
---解:订单号里面,最好是要有分库分表信息。淘宝订单号里面添加了卖家id末2位、买家id末2位。直接定位到具体的库、具体的表去。因为分库、分表的规则,买家库是按照卖家id末尾2位数分,卖家库是按照卖家id末尾两位分。

---问:按照这样,其实就没必要使用订单号来计算了?
---答:确实可行。
a.如果是按照用户id的后4位数取模分散订单数据。那么订单号的生成,可以在后面加上用户id的后4位数。虽然是按照用户id来对订单表分库分表的。其实可以直接根据订单号,知道这个订单在哪个库哪个表了。
b.如果是b2b系统,涉及到卖家和买家。那么可以把卖家和买家的id后面4位都加进去。不过是不是订单号太长了?

---问:按照订单的时间来分表如何?(按时间切分订单数据,业界用得较少)
---答:一月一张表。一年一张表。用户的所有订单,会分散在不同的库、不同的表中。但是会出现2个问题:
---缺1:如果需要分页查询某个用户的所有订单数据,就会出现跨库、跨表查询。效率低。
---解1:限制只能查一个范围内的订单,比如一次只能查询,一年以内或者一个月以内的订单。
---缺2:某个时间集中写入数据,出现瓶颈。如一个月一张表。这个月的订单量暴涨呢。那么写入新的订单数据都会操作这张表。造成性能低下。影响整个业务系统交易。
---解2:尽量将写数据分散到多个表去,达到分流效果,提高系统的并发能力。

 

posted @ 2021-06-02 00:27  liujiacai  阅读(669)  评论(0编辑  收藏  举报