订单中台-3万+QPS高并发系统架构设计

  • 多应用实例全局唯一订单号
  • 分库分表&扩容问题
  • 订单C端查询&B端查询&保存
  • 订单缓存设计&3万+qps
  • 订单配置中心
  • 订单状态机
  • 订单熔断&降级

多应用实例全局唯一订单号(按时间趋势递增,订单id带有业务标示)

      xx-snowflake简介

                    

                    改造版 xx-snowflake方案采用“1+5+41+5+12”的方式组装ID号,使用Zookeeper持久顺序节点的特性自动对snowflake节点配置wokerID。 xx-snowflake是按照下面几个步骤启动的:

  1. 启动Leaf-snowflake服务,连接Zookeeper,在leaf_forever父节点下/snowflake/order-center/forever/检查自己是否已经注册过(是否有该顺序子节点)。(workerid:/snowflake/order-center/forever/192.168.17.197:2181-0000000000)
  2. 如果有注册过直接取回自己的workerID(zk顺序节点生成的int类型ID号),启动服务。
  3. 如果没有注册过,就在该父节点下面创建一个持久顺序节点,创建成功后取回顺序号当做自己的workerID号,启动服务。

        xx-snowflake优点       

                       (1) 基于snowflake算法订单号趋于递增

                     (2) 固定17位+2位业务标示。订单业务标示占据低2位。

                       (3) xx-snowflake对Zookeeper生成机器号做了弱依赖处理,即使Zookeeper有问题,也不会影响服务。Leaf在第一次从Zookeeper拿取workerID后,会在本机文件系统上缓存一个workerID文件。即使ZooKeeper出现问题,同时恰好机器也在重启,也能保证服务的正常运行。这样做到了对第三方组件的弱依赖,一定程度上提高了SLA。

                      (4) 订单id生成规则不容易破解。防止黑客根据算法算到公司的一天的承单量。

2   分库分表&扩容问题

                  2.0   垂直分库分表

                                               按照业务拆分的方式称为垂直分片,又称为纵向拆分,它的核心理念是专库专用。 在拆分之前,一个数据库由多个数据表构成,每个表对应着不同的业务。而拆分之后,则是按照业务将表进行归类,分布到不同的数据库中,从而将压力分散至不同的数据库。 下图展示了根据业务需要,将用户表和订单表垂直分片到不同的数据库的方案。

               垂直分片往往需要对架构和设计进行调整。通常来讲,是来不及应对互联网业务需求快速变化的;而且,它也并无法真正的解决单点瓶颈。 垂直拆分可以缓解数据量和访问量带来的问题,但无法根治。如果垂直拆分之后,表中的数据量依然超过单节点所能承载的阈值,则需要水平分片来进一步处理。

                           ps:垂直分片常见的分片规则以时间维度分表策略

                    2.1 分库分表规则

                                           目前采用的是sharding-jdbc的PreciseShardingAlgorithm,用于处理使用单一键作为分片键的=与IN进行分片的场景。需要配合StandardShardingStrategy使用。

                                      分库规则:  user_id%数据源个数

                                      分表规则:  user_id/数据源个数 % 表个数   

                                   

                    2.3 分库分表扩容 

扩容步骤:

1)等待ds_0_主和ds_1_主的数据同步到其备服务器,即ds_0_从和ds_1_从。 
2)停止写服务,等待主备完全同步后解除ds_0_主与ds_0_从、ds_1_主与ds_1_从之间的主备关系。 
3)修改中间层的映射规则。 
4)开启写服务,用户id哈希值模4等于0、1、2、3的数据将分别写入到ds_0、ds_1、ds_2、ds_3。
5)分别给ds_0、ds_1、ds_2、ds_3增加从库。
 

                        

【问题】我们为什么要选择走按用户维度做为分片键,而不是从订单维度来做?

1、对于C端用户来说,用户都是在登录之后,再去查询订单,按用户维度分片之后,相同用户的订单数据,都会落到同一个数据库的同一个表中,

这样用户查询自己的订单的时候,可以不用跨库操作,减轻服务压力。

2、对以后跟用户中心做交互的时候,都从用户的角度来做,对接起来会比较容易

3、对于toB和toG的多维多查询来说,我们可以在es中建立一层映射关系来应对。

3  订单C端查询&B端查询&保存

                    3.0 c端用户查询逻辑

                     3.1 B端用户查询逻辑

4  redis缓存处理流程图

          4.1 读缓存处理流程图

                       

         4.2 写缓存处理流程图

 

           redis&db数据一致性保证     

         循环2次更新缓存操作,直到更新成功退出循环,这一步主要能减小由于网络瞬间抖动导致的更新缓存失败的概率。对于缓存接口长时间不可用,靠循环调用更新接口是不能补救接口调用失败的。如果循环2次还没有更新成功,发送redis更新失败埋点

      4.3  缓存代码示例:

             4.3.1 获取订单详情(读更新缓存)

             4.3.2 更新or同步订单(更新订单refresh订单缓存)

5 订单配置中心

        5.1 添加Apollo客户端依赖


<dependency>
    <groupId>com.ctrip.framework.apollo</groupId>
    <artifactId>apollo-client</artifactId>
    <version>1.6.0</version>
</dependency>

       5.2 application.yml添加以下配置

app-id: apollo创建项目时的appid

apollo.meta: meta-server地址,一般同config-server地址
apollo.bootstrap.namespaces: 使用配置的命名空间,多个以逗号分隔

   ps: 我们会在打包的时候替换#param#如下设置

apollo具体安装详见: https://gitee.com/lepdou/apollo/

  • 6
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值