订单队列架构思想

前序

一般的订单流程

思考瓶颈点

订单队列

第一种订单队列流程图:

第二种订单队列流程图:

总结

实现队列的选择

解答

第二种队列的 Go 版本例子代码

前序

本文所要分享的思路就是电商应用中常用的订单队列。

一般的订单流程

电商应用中,简单直观的用户从下单到付款,最终完成整个流程的步骤可以用下图表示:

其中,订单信息持久化,就是存储数据到数据库中。而最终客户端完成支付后的更新订单状态的操作是由第三方支付平台进行回调设置好的回调链接 NotifyUrl,来进行的。

补全订单状态的更新流程,如下图表示:

思考瓶颈点

服务端的直接瓶颈点,首先要考虑 TPS。去除细分点,我们主要看订单信息持久化瓶颈点。

在高并发业务场景中,例如 秒杀、优惠价抢购等。短时间内的下单请求数会很多,如果订单信息持久化 部分,不做优化,而是直接对数据库层进行频繁的读写操作,数据库会承受不了,容易成为第一个垮掉的服务,比如下图的所示的常规写单流程:

可以看到,每持久化一个订单信息,一般要经历网络连接操作(链接数据库),以及多个 I/O 操作。

得益于连接池技术,我们可以在链接数据库的时候,不用每次都重新发起一次完整的HTTP请求,而可以直接从池中获取已打开了的连接句柄,而直接使用,这点和线程池的原理差不多。

此外,我们还可以在上面的流程中加入更多的优化,例如对于一些需要读取的信息,可以事先存置到内存缓存层,并加于更新维护,这样在使用的时候,可以快速读取。

即使我们都具备了上述的一些优化手段,但是对于写操作的I/O阻塞耗时,在高并发请求的时候,依然容易导致数据库承受不住,容易出现链接多开异常,操作超时等问题。

在该层进行优化的操作,除了上面谈到的之外,还有下面一些手段:

数据库集群,采用读写分离,减少写时压力

分库,不同业务的表放到不同的数据库,会引入分布式事务问题

采用队列模型削峰

每种方式有各自的特点,因为本文谈的是订单队列的架构思想,所以下面我们来看下如何在订单系统中引入订单队列。

订单队列

网上有不少文章谈到订单队列的做法,大部分都漏了说明请求与响应的一致性问题。

第一种订单队列流程图:

上图是大多文章提到的队列模型,有两个没有解析的问题:

如果订单存在第三方支付情况,① 和 ② 的一致性如何保证,比如其中一处处理失败;

如果订单存在第三方支付情况,① 完成了支付,且三方支付平台回调了notifyUrl,而此时 ② 还在排队等待处理,这种情况又如何处理。

首先,要肯定的是,上面的订单流程图是没有问题的。它有下面的优缺点,所提到的两个问题也是有解决方案的。

优点:

用户无需等待订单持久化处理,而能直接获得响应,实现快速下单

持久化处理,采用排队的先来先处理,不会像上面谈到的高并发请求一起冲击数据库层面的情况。

可变性强,搭配中间件的组合性强。

缺点:

多订单入队时,② 步骤的处理速度跟不上。从而导致第二点问题。

实现较复杂

上面谈及的问题点,我后面都会给出解决方案。下面我们来看下另外一种订单队列流程图。

第二种订单队列流程图:

第二种订单队列的设计模型,注意它的同步等待持久化处理的结果,解决了持久化与响应的一致性问题,但是有个严重的耗时等待问题,它的优缺点如下:

优点:

持久化与响应的强一致性。

持久化处理,采用排队的先来先处理,不会像上面谈到的高并发请求一起冲击数据库层面的情况。

实现简单

缺点:

多订单入队时,持久化单元处理速度跟不上,造成客户端同步等待响应。

这类订单队列,我下面会放出 Golang 实现的版本代码。

总结

对比上面两种常见的订单模型,如果从用户体验的角度去优先考虑,第一种不需要用户等待持久化处理结果的是明显优于第二种的。如果技术团队完善,且技术过硬,也应该考虑第一种的实现方式。

如果仅仅想要达到宁愿用户等待到超时也不愿意存储层服务被冲垮,那么有限考虑第二种。

实现队列的选择

在这里,我们进一步细分一下,实现队列模块的功能有哪些选择。

相信很多后端开发经验比较老道的同志已经想到了,使用现有的中间件,比如知名的 Redis、RocketMQ,以及 Kafka 等,它们都是一种选择。

此外地,我们还可以直接编写代码,在当前的服务系统中实现一个消息队列来达到目的,下面我用图来分类下队列类型。

不同的队列实现方式,能直接导致不同的功能,也有不同的优缺点:

一级缓存优点:

一级缓存,最快。无需链接,直接从内存层获取;

如果不考虑持久化和集群,那么它实现简单。

一级缓存缺点:

如果考虑持久化和集群,那么它实现比较复杂。

不考虑持久化情况下,如果服务器断电或其它原因导致服务中断,那么排队中的订单信息将丢失

中间件的优点:

软件成熟,一般出名的消息中间件都是经过实践使用的,文档丰富;

支持多种持久化的策略,比如 Redis 有增量持久化,能最大程度减少因不可预料的崩溃导致订单信息丢失;

支持集群,主从同步,这对于分布式系统来说,是必不可少的要求。

中间件的缺点:

分布式部署时,需要建立链接通讯,导致读写操作需要走网络通讯。

解答

回到第一种订单模型中:

问题1:

如果订单存在第三方支付情况,① 和 ② 的一致性如何保证?

首先我们看下,不一致性的时候,会产生什么结果:

① 失败,用户因为网络原因或返回其它页面,不能获取结果。而 ② 成功,那么最终该订单的状态是待支付。用户进入到个人订单中心完成订单支付即可;

① 和 ② 都失败,那么下单失败;

① 成功,② 失败,此时用户在响应页面完成了支付动作,用户查看订单信息为空白。

上述的情况,明显地,只有 3 是需要恢复订单信息的,应对的方案有:

当服务端支付回调接口被第三方支付平台访问时,无法找到对应的订单信息。那么先将这类支付了却没订单信息的数据存储起来先,比如存储到表A。同时启动一个定时任务B专门遍历表A,然后去订单列表寻找是否已经有了对应的订单信息,有则更新,没则继续,或跟随制定的检测策略走。

当 ② 是由于服务端的`非崩溃性原因而导致失败时:

失败的时候同时将原始订单数据重新插入到队列头部,等待下一次的重新持久化处理。

当 ② 因服务端的`崩溃性原因而导致失败时:

定时任务B在进行了多次检测无果后,那么根据第三方支付平台在回调时候传递过来的订单附属信息对订单进行恢复。

整个过程订单恢复的过程,用户查看订单信息为空白。

定时任务B 所在服务最好和回调链接 notifyUrl 所在的接口服务一致,这样能保证当 B 挂掉的时候,回调服务也跟随挂掉,然后第三方支付平台在调用回调失败的情况下,他们会有重试逻辑,依赖这个,在回调服务重启时,可以完成订单信息恢复。

问题2:

如果订单存在第三方支付情况,① 完成了支付,且三方支付平台回调了 notifyUrl,而此时 ② 还在排队等待处理,这种情况又如何处理?

应对的方案参考 问题1 的 定时任务B 检测修改机制,或者是另加一个定时任务主动发起查询的机制。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342