首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >订单超时未支付自动关闭的几种实现方案

订单超时未支付自动关闭的几种实现方案

作者头像
业余草
发布2020-02-28 11:29:49
12.8K0
发布2020-02-28 11:29:49
举报
文章被收录于专栏:业余草业余草

做电商,就会遇到订单超时问题,而且还经常被拿来面试提问!

今天,周末放假,抽时间给大家总结了几种订单超时未支付自动关闭的实现方案。

总结来说,订单超时,非常符合业务有“在一段时间之后,完成一个工作任务”的需求。在这类需求中,许多人第一时间想到的就是用定时任务来实现。

定时任务

实现思路比较简单。启动一个计划任务,每隔一定时间处理一次,这种处理方式只是适用比较小而简单的项目。

假设订单表的结构为:

t_order(oid, finish_time, stars, status, …)

然后,定时任务每隔一个 5 分钟(时间自己设定)等会这么做一次:

select oid from t_order where finish_time > 30分钟 and status=0;

update t_order set status=1 where oid in(超时订单id);

如果数据量很大,需要分页查询,分页 update,这将会是一个 for 循环。

但是,这种设计方案有一种明显的不足。

  1. 时效性差,会有一定的延迟,这个延迟时间最大就是每隔一定时间的大小,如果你设置每分钟定时轮询一次,那么理论上订单取消时间的最大误差就有一分钟,当然也可能更大,比如一分钟之内有大量数据,但是一分钟没处理完,那么下一分钟的就会顺延。
  2. 效率低。
  3. 对数据库的压力比较大。

但是,也有优势。

  1. 定时任务,实现起来简单。
  2. 也能很好的做分布式集群。

被动取消

这种实现方案和懒加载的思想一直,就是被动的取消订单。只有当用户或商户查询订单信息时,再判断该订单是否超时,如果超时再进行超时逻辑的处理。

但是这种方式依赖于用户的查询操作触发,这也就是说如果用户不进行查询订单的操作,该订单就永远不会被取消。不会取消的订单,也就可能意味着库存可能被占用。

所以,在实际实现上,可能是被动取消 + 定时任务的这种组合实现方式。这种情况下定时任务的时间可以设置的稍微“长“一点。

缺点:

  1. 会产生额外影响,比如统计,订单数,库存等产生影响。
  2. 影响用户体验,用户打开订单列表可能要处理大量数据,影响显示的实时性。

优点,同样是实现起来简单。

延时消息

这种方式是目前比较普遍的实现方式。

延时消息的这种实现方式,包含两个重要的数据结构:

  1. 环形队列,例如可以创建一个包含 2400 个 slot 的环形队列(本质是个数组)。
  2. 任务集合,环上每一个 slot 是一个 Set。

本质上,就是一个时间轮算法的一个实现。

640?wx_fmt=png
640?wx_fmt=png

时间轮算法可以类比于时钟,如上图箭头(指针)按某一个方向按固定频率轮动,每一次跳动称为一个 tick。这样可以看出定时轮由个3个重要的属性参数,ticksPerWheel(一轮的 tick 数),tickDuration(一个 tick 的持续时间)以及 timeUnit(时间单位),例如当 ticksPerWheel=60,tickDuration=1,timeUnit =秒,这就和现实中的始终的秒针走动完全类似了。

如果当前指针指在 1 上面,我有一个任务需要 4 秒以后执行,那么这个执行的线程回调或者消息将会被放在 5 上。那如果需要在20秒之后执行怎么办,由于这个环形结构槽数只到 8,如果要 20 秒,指针需要多转2圈。位置是在2圈之后的 5 上面(20 % 8 + 1)。

针对时间轮算法或者说延时消息,目前有很多消息队列都支持,比如 RocketMQ,RabbitMQ 等(公众号回复对应关键词获取对应的视频教程)。

扩展 JDK 的延时队列

JDK 自带了一个延时队列 DelayQueue,这是一个无界阻塞队列,该队列只有在延迟期满的时候才能从中获取元素,放入 DelayQueue 中的对象,是必须实现 Delayed 接口的。

640?wx_fmt=png
640?wx_fmt=png

如果公司允许,可以在此基础上,扩展成一个分布式的,支持集群的延时队列。但是缺点是,难度较高,小公司根本没有这个机会来做。

Redis 缓存

利用 redis 的 zset。zset是一个有序集合,每一个元素(member)都关联了一个 score,通过 score 排序来取集合中的值。

我们将订单超时时间戳与订单号分别设置为 score 和 member。系统扫描第一个元素判断是否超时,具体如下图所示。

640?wx_fmt=png
640?wx_fmt=png

但是,这种实现方式,在高并发条件下,多消费者可能会取到同一个订单号。当初,我的同事,不得已而又加来一个分布式锁来处理。但是,性能下降严重。后来又做了很多变种,最终还是采用了延时消息。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-10-26 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档