前序
本文所要分享的思路就是电商应用中常用的订单队列。
一般的订单流程
电商应用中,简单直观的用户从下单到付款,最终完成整个流程的步骤可以用下图表示:
其中,订单信息持久化
,就是存储数据到数据库中。而最终客户端完成支付后的更新订单状态
的操作是由第三方支付平台进行回调设置好的回调链接 NotifyUrl
,来进行的。
补全订单状态的更新流程,如下图表示:
思考瓶颈点
服务端的直接瓶颈点
,首先要考虑 TPS
。去除细分点,我们主要看订单信息持久化
瓶颈点。
在高并发业务场景中,例如 秒杀
、优惠价抢购
等。短时间内的下单请求数会很多,如果订单信息持久化
部分,不做优化,而是直接对数据库层进行频繁的
读写操作,数据库会承受不了,容易成为第一个垮掉的服务,比如下图的所示的常规写单流程:
可以看到,每
持久化一个订单信息,一般要经历网络连接操作(链接数据库),以及多个 I/O
操作。
得益于连接池
技术,我们可以在链接数据库的时候,不用每次都重新发起一次完整的HTTP请求,而可以直接从池中获取已打开了的连接句柄,而直接使用,这点和线程池的原理差不多。
此外,我们还可以在上面的流程中加入更多的优化,例如对于一些需要读取的信息,可以事先存置到内存缓存层,并加于更新维护,这样在使用的时候,可以快速读取。
即使我们都具备了上述的一些优化手段,但是对于写操作
的I/O
阻塞耗时,在高并发请求
的时候,依然容易导致数据库承受不住,容易出现链接多开异常
,操作超时
等问题。
在该层进行优化的操作,除了上面谈到的之外,还有下面一些手段:
-
数据库集群,采用读写分离,减少写时压力
-
分库,不同业务的表放到不同的数据库,会引入分布式事务问题
-
采用队列模型削峰
每种方式有各自的特点,因为本文谈的是订单队列
的架构思想,所以下面我们来看下如何在订单系统中引入订单队列。
订单队列
网上有不少文章谈到订单队列的做法,大部分都漏了说明请求与响应的一致性问题。
第一种订单队列
流程图:
上图是大多文章提到的队列模型,有两个没有解析的问题:
-
如果订单存在第三方支付情况,① 和 ② 的一致性如何保证,比如其中一处处理失败;
-
如果订单存在第三方支付情况,① 完成了支付&