zoukankan      html  css  js  c++  java
  • (转)【订单号存储】最硬核实用的分库分表操作指南

    原文: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:尽量将写数据分散到多个表去,达到分流效果,提高系统的并发能力。

    技术链接
  • 相关阅读:
    DBCP数据源使用
    实例介绍Cocos2d-x开关菜单
    Material UI:很强大的CSS框架
    stl之hash_multimap
    使用OpenCV滑动条写成的简单调色器,实时输出RGB值
    Android中怎样自己制作su
    华南运维论坛 2015-07-25
    POJ2417 Baby-Step-Gaint-Step 算法
    《网络编程》套接字地址与名字转换
    Hibernate缓存
  • 原文地址:https://www.cnblogs.com/liujiacai/p/14839458.html
Copyright © 2011-2022 走看看