订单系统理解篇

对订单系统的理解

经过一个月开发订单系统,阅读了大量的相关成熟的技术文章,对于订单系统有了自己一定的理解。订单系统的整体下来最难的点在于订单系统库存、支付、订单之间的关系(这里没有加入优惠卷部分),也就是订单的创建过程,需要考虑到非常多的问题,如果是同一个服务下,使用MySQL出现问题的可能性很小,但并发情况下,使用缓存和调用服务的过程,存在一致性问题事务性问题,使用了消息队列以及超时问题造成了幂等性问题,这也是造成订单系统开发的难点。

订单系统与支付系统关系

其实订单系统需要维护自身的正确性,需要多个组件进行保证,而对于支付系统而言,肯定更加的复杂。在测试时间的时候,会发现订单系统所花费的时间其实整体过程和支付系统相差不多,虽然我的设计会根据将订单的创建与支付在同一个流程2个事务中完成。但这样子很大程度浪费将近一半的时间在支付系统上,所以应该创建往后,将支付时间直接浪费在用户上,才是最合理的。

支付系统的优化,支付系统之前需要花费0.8s才能完成一次请求,这个时间够创建4~6订单了,这个是没办法容忍的,优化思路从2个反面,优化netty的rpc服务,优化数据库。这个部分其实没怎么用上缓存,因为创建支付过程没几个状态,需要修改部分很少,大部分是读取,而读取则只需要一个到2个缓存就够了。对于netty的优化,之前的rpc过程使用的是jdk的反射,之后全部换成了cglib的进行方法反射。而对于连接问题来说,每次服务都会创建一个客户端,但是使用了连接池后发现其实效果差不过。而且连接池也会存在超时问题。对于数据库的优化,主要是加了几个索引,对主键生成修改,之前使用uuid,当订单数目到达了一定数目后,插入明显慢了,也能理解。uuid是字符串,且是完全随机,这插入过程索引频繁的修改,对性能不好,所以之后id生成使用了雪花算法索引是一个bigint,而且基于雪花算法的生成,总是有序的。最后总体性能在本地运行,远程组件的情况下,是0.4s的延迟。将服务部署到服务器上,由于物理上靠近,整体的速度惊人,比本机快30倍(物理距离看来还是很重要的)。

订单系统设计原则

整体设计上应该凸显早失败的原则,有序驱动补偿。订单系统,很多时候有库存限制,如果库存不够,根本没必要走到消息队列哪一个步骤,应该在创建订单的消息之前的时候,直接噶掉,还有如果服务压根处理不了那么多请求,就不要接受了要不然直接g了不太好,或者采取动态扩容,我目前还没实现(库存系统的原因)。其实早失败对整体服务感觉维护起来很重要,之后的部分为了一致性采取了太多了限制于补偿,我第一步就g那完全可以剩下很多的事情。

有序驱动也就是一个,对过程容忍行为吧。比如创建订单可以容忍支付失败,但是绝不能容易扣除库存失败。支付失败必须要在有订单的基础上才行。也就是过程必须是有序的。订单一旦创建成功,必须是在库存扣除成功的前提,而支付一旦成功,必须在订单创建入库的原则下。也就是事务性吧,但这些操作写不到一个事务里面,也就是有序的事务性,但是为了完整事务,但即使失败也必须将失败的事务补偿回来。

补偿。如果过程是完整,也就不会这么多事情,但是肯定会出现订单创建失败,或者支付失败或者丢失的情况。这种情况下需要判断下一个操作是否成功,再来决定返还事宜。如果创建订单操作失败了,必须将订单的库存返还回来才行。支付由于超时或者其他的异常错误,导致没有明确的返回结果,从而导致事务回滚或者未生效,这是不被允许的,应该尽快查询支付状态,修改订单状态。

强迫进行。比如说,用户选择创建订单,那么订单除去库存不足的情况,就应该被成功创建(组件故障导致的需要紧急处理),也就是最终成功性。不能说系统除了故障就创建失败了吧,再比如用户既然提出了支付,那么最好只有2种结果,支付前不够导致的失败,和最终的成功。用户进行重试,理论上来说并不是一个很好的体验,目前来说只能通过redis和mq结合补偿才能完成这个。

高并发

前一个版本是同步处理消息,这个版本采用消息队列处理订单生成消息。

此时做的事情有3件。

  1. 限流
  2. 预判断库存
  3. 生成订单号

由于是异步处理,必须要有一个回调查询过程,所以此时的依据则是订单号了。

订单号此时必须生成,用于前端的回调查询,此后的订单号必须保持相同。

对于订单生成,会按照一次提交的商品,按照商铺进行归类,有几个商铺生成几个订单

消息队列的异步操作处理,虽然失去了同步,但是在请求量很高的情况下,可以达到晓峰的效果,也能保证消耗的持续与稳定。但必须预防消息的积压问题,消息积压,最好的办法是多几个消费者,实在不行就把不能处理的订单量给拒绝算了,代码优化感觉只会占很小的一部分,架构的设计才是核心。

demo

request body

{
    "uid" : 1,
    "to_uid": 2,
    "origin_price": 29.99,
    "actual_price": 29.99,
    "pay_at_once": true,
    "commodity_details": [
         {
                "actual_price": 29.99,
                "commodity_id": 1,
                "good_type": 1,
                "page_type": 0,
                "prices": 29.99,
                "user_id": 100001,
                "num": 1
            },
            {
                "actual_price": 49.99,
                "commodity_id": 2,
                "good_type": 1,
                "page_type": 0,
                "prices": 49.99,
                "user_id": 100002,
                "num": 1
            }
    ]
}

response

{
    "data": {
        "order_no": [
            "14401939662076689831000011679206719",
            "14401939662076689841000011679206719"
        ]
    },
    "message": "OK",
    "status": 200
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值