百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

微软一面:订单超时未支付,如何自动关闭?

mhr18 2025-03-25 15:26 28 浏览 0 评论

hi,你好,我是猿java

最近,有小伙伴私信反馈微软一面的系统设计题:订单超时未支付,如何自动关闭?

说实话,微软能问出这种面试题确实很诧异,难道是互联网人已经大量涌进了微软这个养老基地,开始卷它?言归正传,有网购经验的小伙伴应该知道,如果订单在规定的时间内没有支付,订单就会被系统自动关闭,作为技术人员,该如何设计这个功能,今天我们来分析 4种有概括性的方案。

说明:

  • 规定的时间:即超时时间,这个因平台而异,有的场景是 10分钟超时,比如 12306 购票,有的平台是 15分钟或者 30分钟超时,有些秒杀场景是 1分钟超时,具体超时值需要根据具体的业务来定。
  • 自动关闭的原因:对于有库存的业务,需要释放库存,否则容易导致少卖。

方案1: 定时器

定时器应该是我们最可能想到的方案,通过定时器去数据库轮询待支付的订单信息,然后在业务代码中判断订单是否超时,更新订单状态。

实现思路

下单的时候把超时需要关闭订单的具体时间值(pay_expire_time)保存到表里,给pay_expire_time字段添加一个索引,然后设置一个定时器,每 3s/5s 去数据库查询一次数据,查询 SQL 如下:

select id from order where order_status = '待支付' && pay_expire_time > now()

优点

定时器方案最大的优点就是实现简单

缺点

  1. 需要定时从数据库拉取数据,对数据库会产生一定的压力
  2. 需要将数据加载到内存中进行业务逻辑处理,如果拉取的数据量比较大,可能会消耗过多的内存导致OOM
  3. 定时器是周期性的,对于超时订单的关闭可能存在延时

适用场景

适用于数据量比较小的业务场景,比如,很多小公司在业务处于 0-1 的过程中,该方案比较常见。

方案2: 被动关闭

服务器不做订单的主动关闭,而是在客户端拉取订单时按需被动关闭订单,比如,客户端通过接口获取服务器的时间以及订单超时时间,然后计算并判断订单是否超时,如果超时,将订单显示成超时的样式, 并隐式向服务器发送一个订单超时关闭的请求,服务器再做相应的逻辑处理。

优点

  • 实现简单
  • 按需处理订单超时,客户端需要用到数据再做判断

缺点

  • 订单长时间未关闭,在业务意义上可能是脏数据
  • 客户端需要做超时的逻辑判断并且发送超时关闭请求

适用场景

适用于数据量比较小的业务场景,被动关闭通常会结合定时器方案使用。

方案3: MQ延时消息

有些 MQ有延时消息的特性,比如阿里开源的 RocketMQ,用户创建订单时,同时往 MQ中发送一条延时消息,用户支付成功后,删除对应的延时消息(开源版本的没有此功能),当消费者消费到消息时再做超时的相关处理

优点

  • 利用中间件 MQ的特性,避免业务端自己实现

缺点

  • 如果使用开源的 Apache RocketMQ 4.x版本,消息延时只有特定的 18个级别,所以业务的超时时间要和 RocketMQ的延时级别相匹配才能使用
  • 强依赖中间件 MQ,所以 MQ的稳定性以及是否丢消息直接影响该功能
  • 使用开源版的 RocketMQ,没有删除延时消息的功能,因此需要对每条消息都做超时判断,增加了很多无效的数据处理
  • 如果数据量比较大,MQ可能会堆积产生延时

注意:

在 RocketMQ 4.x中 只有 1s 5s 10s 30s 1m 2m 3m 4m 5m 6m 7m 8m 9m 10m 20m 30m 1h 2h 18个固定Level的延迟时间

在 RocketMQ 5.x,支持任意时间的延迟消息,官方解决的 issue

适用场景

适用于搭建了 RocketMQ的公司,想利用 RocketMQ的延时消息来实现该功能

方案4: 超时中心

很多大厂都有自己的分布式超时系统 TOC(Timeout Coordinator System),不同的公司可能叫法不一样,这里给出一种实现思路:

实现思路

1. 订单创建

  • 用户通过前端下单,请求发送到OMS(Order Management System)订单管理系统
  • OMS创建订单,并将订单状态设置为“待支付”或类似的初始状态

2. 注册超时事件

  • 在订单创建的同时,OMS向 TOC注册一个超时事件
  • 超时事件包含了订单ID、超时时间(例如30分钟)和超时后需要执行的动作(例如关闭订单)

3. 超时监控

  • TOC系统开始监控这个订单的超时事件
  • 如果在设定的超时时间内,用户完成了支付,OMS会更新订单状态并通知 TOC取消超时事件

4. 超时处理

  • 如果超时时间到达,而订单状态仍然是“待支付”,TOC将触发超时动作
  • TOC通知 OMS订单已超时

5. 订单关闭

  • OMS收到 OTC超时通知后,执行订单关闭操作
  • OMS将订单状态更新为“已关闭”或“超时关闭”

6. 超时后处理

  • OMS可能需要处理一些后续任务,如释放库存、退还优惠券等
  • 完成这些操作后,该订单的超时处理流程结束

优点

  • 专门的人做专门的事,性能,稳定性,扩展性有保障
  • 可以处理海量数据

缺点

  • 实现和维护成本比较高
  • 实现复杂度比较高,方案中可能会涉及分布式调度,MQ等技术栈

适用场景

适合数据量比较大的中大型公司,需要专门的团队负责

如何选择?

架构领域有句经典名言:没有最好的架构,只有够用(合适)的架构。

这个理论用于订单超时关闭场景同样适用,分布式超时中心方案看起来高大上,而且能处理海量数据,但是,如果把这套方案用于几个人的团队,有一种杀鸡用牛刀的架势,可能不但解决不了问题,还会给团队带来技术难题和成本负担。

因此,架构一定要基于业务,方案也一定要基于业务。

对于定时器方法,看起来简单粗暴,但是很多公司的业务在 0-1的过程中,它就是首选,因为实现的成本很低,没有什么技术难点, 假设每条订单的数据大小是 1K,5万条订单的数据大概在 50M左右,用定时器把数据加载到内存中处理也是ok的,所以该方案适合每天的订单量在万级别,或者再保守一些,每日订单总量在 1万以下。

对于 MQ延时消息方案,首先需要考虑自建 MQ 还是购买 MQ云产品,以及两种方案带来的技术难点或者购买成本,基于先有 MQ这个条件再看它适合的业务场景,在根据每日的订单量是百万级别,十万级别还是万级别来选择 MQ的配置。

分布式超时中心方案技术难度和维护成本都比较高,一般适合一些独角兽企业,大厂或者财力和技术能力都不错的公司。

总结

本文分析了具有概括性的 4种订单超时关闭方案,也是业内使用比较多的方案,可能每个公司实现的细节或者叫法略有差异,但是思想是相通的。

当然还有其他方案实现,比如 Redis,但是不推荐

通过本文,我们可以根据不同的业务体量给出不同的方案或者设计思路,以及各个方案的优缺点,具体细节可以结合具体业务细节。

没有最好的架构,只有够用(适合)的架构,很多时候在选择方案的时候一定要结合实际业务,切勿过度设计,但是也不能缺乏设计的能力

原文链接:
https://juejin.cn/post/7361715712992935975

相关推荐

B站收藏视频失效?mybili 收藏夹备份神器完整部署指南

本内容来源于@什么值得买APP,观点仅代表作者本人|作者:羊刀仙很多B站用户都有过类似经历:自己精心收藏的视频突然“消失”,点开一看不是“已被删除”,就是“因UP主设置不可见”。而B站并不会主动通知...

中间件推荐初始化配置

Redis推荐初始化配置bind0.0.0.0protected-modeyesport6379tcp-backlog511timeout300tcp-keepalive300...

Redis中缓存穿透问题与解决方法

缓存穿透问题概述在Redis作为缓存使用时,缓存穿透是常见问题。正常查询流程是先从Redis缓存获取数据,若有则直接使用;若没有则去数据库查询,查到后存入缓存。但当请求的数据在缓存和数据库中都...

后端开发必看!Redis 哨兵机制如何保障系统高可用?

你是否曾在项目中遇到过Redis主服务器突然宕机,导致整个业务系统出现数据读取异常、响应延迟甚至服务中断的情况?面对这样的突发状况,作为互联网大厂的后端开发人员,如何快速恢复服务、保障系统的高可用...

Redis合集-大Key处理建议

以下是Redis大Key问题的全流程解决方案,涵盖检测、处理、优化及预防策略,结合代码示例和最佳实践:一、大Key的定义与风险1.大Key判定标准数据类型大Key阈值风险场景S...

深入解析跳跃表:Redis里的"老六"数据结构,专治各种不服

大家好,我是你们的码农段子手,今天要给大家讲一个Redis世界里最会"跳科目三"的数据结构——跳跃表(SkipList)。这货表面上是个青铜,实际上是个王者,连红黑树见了都要喊声大哥。...

Redis 中 AOF 持久化技术原理全解析,看完你就懂了!

你在使用Redis的过程中,有没有担心过数据丢失的问题?尤其是在服务器突然宕机、意外断电等情况发生时,那些还没来得及持久化的数据,是不是让你夜不能寐?别担心,Redis的AOF持久化技术就是...

Redis合集-必备的几款运维工具

Redis在应用Redis时,经常会面临的运维工作,包括Redis的运行状态监控,数据迁移,主从集群、切片集群的部署和运维。接下来,从这三个方面,介绍一些工具。先来学习下监控Redis实时...

别再纠结线程池大小 + 线程数量了,没有固定公式的!

我们在百度上能很轻易地搜索到以下线程池设置大小的理论:在一台服务器上我们按照以下设置CPU密集型的程序-核心数+1I/O密集型的程序-核心数*2你不会真的按照这个理论来设置线程池的...

网络编程—IO多路复用详解

假如你想了解IO多路复用,那本文或许可以帮助你本文的最大目的就是想要把select、epoll在执行过程中干了什么叙述出来,所以具体的代码不会涉及,毕竟不同语言的接口有所区别。基础知识IO多路复用涉及...

5分钟学会C/C++多线程编程进程和线程

前言对线程有基本的理解简单的C++面向过程编程能力创造单个简单的线程。创造单个带参数的线程。如何等待线程结束。创造多个线程,并使用互斥量来防止资源抢占。会使用之后,直接跳到“汇总”,复制模板来用就行...

尽情阅读,技术进阶,详解mmap的原理

1.一句话概括mmapmmap的作用,在应用这一层,是让你把文件的某一段,当作内存一样来访问。将文件映射到物理内存,将进程虚拟空间映射到那块内存。这样,进程不仅能像访问内存一样读写文件,多个进程...

C++11多线程知识点总结

一、多线程的基本概念1、进程与线程的区别和联系进程:进程是一个动态的过程,是一个活动的实体。简单来说,一个应用程序的运行就可以被看做是一个进程;线程:是运行中的实际的任务执行者。可以说,进程中包含了多...

微服务高可用的2个关键技巧,你一定用得上

概述上一篇文章讲了一个朋友公司使用SpringCloud架构遇到问题的一个真实案例,虽然不是什么大的技术问题,但如果对一些东西理解的不深刻,还真会犯一些错误。这篇文章我们来聊聊在微服务架构中,到底如...

Java线程间如何共享与传递数据

1、背景在日常SpringBoot应用或者Java应用开发中,使用多线程编程有很多好处,比如可以同时处理多个任务,提高程序的并发性;可以充分利用计算机的多核处理器,使得程序能够更好地利用计算机的资源,...

取消回复欢迎 发表评论: