场景:在电商购物下单后确认付款前,会有一个支付剩余时间提示。如果超过支付时间,订单就会被自动取消。
案例:距离下单超过20min进行订单取消操作,前端会有个倒计时用于提醒用户当前还有多久订单会被取消。前端页面可以从下单页面退出,切换等其他操作。
定时轮询
-
定时任务去轮询数据库,取消即将超时的订单。 (查询条件是 距离当前时间 超过20min 的订单下单时间,将订单标记为超时,下单时间加索引)
-
前端进入收银台后,通过API去查询当前订单状态。
-
如果超时则将页面展示超时页面。(定时任务将订单状态改为超时状态)
-
如果没有超时则从返回结果中的下单时间开始进行倒计时。倒计时结束后前端请求取消订单API,服务端API逻辑:
A. 服务端查询此订单已经被置为超时,或者是下单时间和当前时间很接近 3s内,则修改订单为超时状态。【任务计划可能进行较晚】 返回客户端true,用户展示超时页面。
B. 服务端检查此订单未超时,客户端提前进行超时状态。返回false,并且返回客户端下单信息,客户端更新自己正确倒计时。
优点:实现简单。
缺点:轮询会影响到查询效率。如果有频繁的销量统计信息会影响到查询效率。
被动取消
倒计时由客户端去做,但是客户端定时去服务端检查,修正倒计时的时间。
那么,这个订单超时自动取消,也可以由客户端去做:
-
用户留在收银台的时候,客户端倒计时+主动查询订单状态,服务端每次都去检查一下订单是否超时、剩余时间
-
用户每次进入订单相关的页面,查询订单的时候,服务端也检查一下订单是否超时
这种方式实现起来也比较简单,但是它也有缺点:
依赖客户端,如果客户端不发起请求,订单可能永远没法过期,一直占用库存。
可以被动取消+定时任务,通过定时任务去做兜底的操作。 【也就是上面所说的定时轮询方式】
延时消息
利用延时消息了,可以使用RocketMQ、RabbitMQ、Kafka的延时消息,消息发送后,有一定延时才会投递。【京东采用此种方案】
优点:是比较高效、好扩展。
缺点:是引入了新的技术组件,增加了复杂度