很多交易场景下的订单都会设置一个支付时间,超过该时间则会自动取消该订单(或者叫已过期),本文将会简述我是如何去实现这一功能的。
01
—
定时轮询不可取
直接进行数据库定时轮询是很多人第一时间想到的方式,但并不可取,其原因主要有以下两点:
1、不论怎么设置轮询时间都不合适,由于用户提交订单的时间很随机,所以如果你设置每分钟定时轮询一次,那么理论上订单取消时间的最大误差就有一分钟,轮询的时间间隔越大,误差就越大,当然,你可能会说那干脆每秒都来一次,那我觉得还是先把你拖出去祭天了吧。
2、不论是对于服务器、还是数据库都过分占用资源,即使你在业务上能忍受一分钟的误差,每分钟轮询也是极其浪费资源的。
所以,直接使用定时轮询的方式不可取,但其还是可以作为一个保底的方式低频辅助使用(处理极端情况)。
02
—
被动取消
被动取消的方式很简单:只有当用户查询订单信息时,我们再判断该订单是否超时,如果超时再进行超时逻辑的处理。
但是这种方式依赖于用户的查询操作触发,这也就是说如果用户不进行查询订单的操作,该订单就永远不会被取消。
03
—
主动取消
为了避免轮询并且在服务端主动取消订单,可以使用类似于消息队列的方式,比如 redis 的 pub/sub 服务。
如上图所示,应用服务在成功提交订单(未支付)后,延时(时长就是支付的最大时间间隔)发布该订单到 redis 的自定义 channel ,而订单取消服务则订阅同一个 channel,一旦接收到消息则进行订单取消的逻辑处理。同时我们可以看到这种消息队列的方式很自然的解耦了服务。
另外在 node.js 中操作 redis 推荐你使用 ioredis 这个库,更简单好用。同时说到消息队列,就不得不提 MQ,专业的 MQ 肯定更加稳定可靠,但会附带更大的使用成本,若在这方面没有重点需求,岂非杀鸡用牛刀。
当然上述方式更推荐结合使用,本篇完。
领取专属 10元无门槛券
私享最新 技术干货