深入剖析如何设计订单超时自动取消的功能
我们在美团 APP 下单,假如没有立即支付,进入订单详情会显示倒计时,如果超过支付时间,订单就会被自动取消。
这篇文章,笔者想以架构师的视角,深入剖析如何设计订单超时自动取消的功能。
1 定时任务
首先,我们非常自然的想到定时任务的方案。
方案流程:
- 每隔 30 秒查询数据库,取出最近的 N 条未支付的订单。
- 遍历查询出来的订单列表,判断当前时间减去订单的创建时间是否超过了支付超时时间,如果超时则对该订单执行取消操作。
这种方案会间隔对数据库造成一定的 IO 压力,但工程实现相对简单。
网上有很多的定时任务实现策略,我们可以简单划分为单机版和集群版。
笔者曾负责过彩票订单、专车订单等业务,在这些业务场景里,都没有使用单机版定时任务。
因为业务系统都是集群部署,假如使用单机版模式,可能出现多台不同机器实例同时执行任务的风险。
虽然我们可以通过加锁的方式适当规避,从架构设计的角度但总是不够优雅。
接下来,笔者会介绍亲身经历的三种集群定时任务。
01、 Quartz + JDBCJobStore
Quartz 是一款 Java 开源任务调度框架,它支持集群模式。
图中,Quartz 的集群模式需要在数据库中添加11张表,对业务系统有一定的侵入性。
笔者曾经服务的一家彩票公司,订单调度中心就是使用 Quartz 的集群模式,实现日均百万订单的调度处理。
需要特别注意的是:
基于底层数据库悲观锁的机制, Quartz 的集群模式性能并不高,假如执行频率高的任务数超过一定数量级,可能存在一定的问题。
02、 Elastic-Job
ElasticJob 定位为轻量级无中心化解决方案,使用 jar 的形式提供分布式任务的协调服务。
ElasticJob 从本质上来讲 ,底层任务调度还是通过 Quartz ,它的优势在于可以依赖 Zookeeper 这个大杀器 ,将任务通过负载均衡算法分配给应用内的 Quartz Scheduler 容器,
举例:应用A有五个任务需要执行,分别是 A,B,C,D,E。任务E需要分成四个子任务,应用部署在两台机器上。
图中,应用 A 在启动后, 5个任务通过 Zookeeper 协调后被分配到两台机器上,通过 Quartz Scheduler 分开执行不同的任务。
相比 Quartz 集群模式,ElasticJob 的可扩展性更高,同时性能也更好。
但是 ElasticJob 的控制台非常粗糙,主要原因还是基于它的实现机制 (Quartz + zookeeper),所以 ElasticJob 更多的还是定位于框架,而不是一个调度平台。
03、XXL-JOB
XXL-JOB 是一个使用最广泛的分布式任务调度平台。
业务系统和调度平台分开部署,我们在调度中心上配置应用以及其定时任务,当任务需要执行时,调度平台会触发业务系统的任务,业务系统执行完任务之后,反馈给调度平台任务执行的结果。
业务系统和调度平台都可以水平扩展实现高可用,同时在调度平台可以配置灵活的调度策略(比如重试机制等)。
笔者非常认可这种模式。很多公司比如神州专车、美团都有自己自研的任务调度平台。这种模式非常适合多团队协作,便于调度任务的统一管理。
2 延时消息
延时消息是一种非常优雅的模式。订单服务生成订单后,发送一条延时消息到消息队列。消息队列在消息到达支付过期时间时,将消息投递给消费者,执行取消订单的逻辑。
延时消息有三种技术选型:
1、消息队列 RocketMQ
RocketMQ 4.X 版本默认支持 18 个 level 的延迟消息, 通过 broker 端的 messageDelayLevel 配置项确定的。
RocketMQ 5.X 版本支持任意时刻延迟消息,客户端在构造消息时提供了 3 个 API 来指定延迟时间或定时时间。
2、自研延迟服务
基于 RocketMQ 4 内置的延迟消息只能支持几个固定的延迟级别,快手、滴滴开发了单独的 Delay Server 来调度延迟消息。
上图这个结构没有直接将延迟消息发到 Delay Server,而是更换 Topic 以后存入 RocketMQ。这样的好处是可以复用现有的消息发送接口(以及上面的所有扩展能力)。对业务来说,只需要在构造消息的时候额外指定一个延迟时间字段即可,其它用法都不变。
自研单独的 Delay Server 不仅可以适配 RocketMQ 4.X , 也可以适配 Kafka ,说实话,这个是一个非常实用的方案。
3、Redis 延迟队列
Redis 延迟队列是一个轻量级的解决方案,开源成熟的实现是 Redission 。
图中,我们定义两个集合:
1、zset 集合
生产者将任务信息发送到 zset 集合,value 是任务编号,score 是任务执行时间戳。
2、list 集合
守护线程检测 zset 集合中到期的任务,若任务到期,将任务编号转移到 list 集合 , 消费者从 list 集合弹出任务,并执行任务逻辑。
笔者需要强调的是:
Redis 虽然可以实现延迟消息的功能,但 Redis 并不是真正意义上的消息队列,在使用过程中还是有小概率会丢失消息。
3 并发口诀:一锁二判三更新
不管我们使用定时任务还是延迟消息时,不可避免的会遇到并发执行任务的情况 (比如重复消费、调度重试等)。
当我们执行任务时,我们可以按照一锁二判三更新这个口诀来处理。
- 锁定当前需要处理的订单。
- 判断订单是否已经更新过对应状态了
- 如果订单之前没有更新过状态了,可以更新并完成相关业务逻辑,否则本次不能更新,也不能完成业务逻辑。
- 释放当前订单的锁。
4 总结
这篇文章,笔者总结了订单超时自动取消方案的两种流派:定时任务和延迟消息。
1、定时任务
- 每隔 30 秒查询数据库,取出最近的 N 条未支付的订单。
- 遍历查询出来的订单列表,判断当前时间减去订单的创建时间是否超过了支付超时时间,如果超时则对该订单执行取消操作。
定时任务实现策略,我们可以简单划分为单机版和集群版。
笔者并不认可单机版,背八股文当然可以,订单自动取消这个业务场景,生产环境还是要慎重。
集群版有三种方式:Quartz + JDBCJobStore、Elastic-Job 、XXL-JOB 。
每种方式各有优缺点,因为自研过任务调度系统的缘故,笔者更倾向于任务调度平台 XXL-JOB 这种方式。
2、延迟消息
延时消息是一种非常优雅的模式。订单服务生成订单后,发送一条延时消息到消息队列。消息队列在消息到达支付过期时间时,将消息投递给消费者,执行取消订单的逻辑。
本文介绍了三种方式:消息队列 RocketMQ、自研延迟服务、Redis 延迟队列。
假如技术团队基础架构能力很强,笔者推荐使用 RocketMQ 或者自研延迟服务。
假如技术团队仅仅想用轻量级的实现,可以选择 Redis 延迟队列。
不管是使用定时任务还是延迟消息,都需要考虑并发问题,请记住一个简单的口诀:一锁二判三更新。
最后,没有完美的技术,只有最合适的技术。
做技术选型时,一定要结合业务场景,研发效率,运维成本,技术储备等因素,做出合理的选择。
如果我的文章对你有所帮助,还请帮忙点赞、在看、转发一下,你的支持会激励我输出更高质量的文章,非常感谢!

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Databend 开源周报第 132 期
Databend 是一款现代云数仓。专为弹性和高效设计,为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务:https://app.databend.cn 。 What's On In Databend 探索 Databend 本周新进展,遇到更贴近你心意的 Databend 。 提供对 CREATE [ OR REPLACE ] 的全面支持 Databend 现已提供对 CREATE [ OR REPLACE ] 语法糖的全面支持,以覆盖潜在的 DROP IF EXISTS ... + CREATE ... 用例。 目前支持该语法糖的对象包括:DATABASE、TABLE、VIEW、AGGREGATING INDEX、STREAM、CONNECTION、FUNCTION、FILE FORMAT、MASKING POLICY 等。 如果您想了解更多信息,欢迎联系 Databend 团队,或查看下面列出的资源。 Issue #14299 | tracking: CREATE OR REPLACE Code Corner 一起来探索 Databend 和周边生态中的代码片段或项目。 ...
- 下一篇
Sora背后团队大揭秘!天才00后?
现在世界上最受关注的技术团队是哪一支? Sora 团队,已经来到聚光灯中心。 不仅项目负责人评论区被挤爆,成了𝕏最火“景点”。 当 OpenAI 出手发布 Sora 之后,给人一种降维打击的感觉—— 效果和之前的技术相比高出了几个档次。这就难免会让人好奇,到底是什么样的人才能做出这样炸裂的工具的呢?今天我们就来盘点一下Sora背后的团队成员。 这些参与者中,已知的核心成员包括研发负责人:Tim Brooks、Bill Peebles、系统负责人: Connor Holmes 等。这些成员的信息也成为了众人关注的焦点。 重点来介绍一下Sora的几位主要负责人,包括 Tim 和 Bill 在内,Sora 的主要负责人一共有三名(以下排名不分先后) Sora的总负责人Tim Brooks,博士毕业于 UC Berkeley 的「伯克利人工智能研究所」BAIR,导师为 Alyosha Efros。 Tim 本科就读于卡内基梅隆大学,主修逻辑与计算,辅修计算机科学,其间在 Facebook 软件工程部门实习了四个月。 2017 年,本科毕业的 Tim 先到 Google 工作了近两年,...
相关文章
文章评论
共有0条评论来说两句吧...