(转)订单超时自动关闭的实现方案总结

本文探讨了四种处理定时任务的方法:定时轮询、被动取消、延时消息及环形队列实现。对比了它们的优缺点,如时效性、效率和用户体验。延时消息方案通过环形队列和任务集合,解决了订单自动关闭评价的需求,提高了效率并实现了秒级精度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

统一来说,业务有“在一段时间之后,完成一个工作任务”的需求。
实现这种定时任务有哪些方法呢,来总结一下想到的方法。
一、定时轮询
这是一个比较直接的思路,启动一个计划任务,每隔一定时间处理一次,这种处理方式只是适用比较小而简单的项目。
假设订单表的结构为:t_order(oid, finish_time, stars, status, …),更具体的,定时任务每隔一个小时会这么做一次:
select oid from t_order where finish_time > 30minite and status=0;
update t_order set stars=5 and status=1 where oid in[…];
如果数据量很大,需要分页查询,分页update,这将会是一个for循环。

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

二、被动取消
被动取消的方式很简单:只有当用户查询订单信息时,我们再判断该订单是否超时,如果超时再进行超时逻辑的处理。
但是这种方式依赖于用户的查询操作触发,这也就是说如果用户不进行查询订单的操作,该订单就永远不会被取消。
不足:
1、会产生额外影响
比如统计,订单数量等产生影响
2、影响用户体验
用户打开订单列表可能要处理大量数据,影响显示的实时性。
三、延时消息
延时消息设计与实现
高效延时消息,包含两个重要的数据结构:
(1)环形队列,例如可以创建一个包含3600个slot的环形队列(本质是个数组)
(2)任务集合,环上每一个slot是一个Set
 
同时,启动一个timer,这个timer每隔1s,在上述环形队列中移动一格,有一个Current Index指针来标识正在检测的slot。
 
Task结构中有两个很重要的属性:
(1)Cycle-Num:当Current Index第几圈扫描到这个Slot时,执行任务
(2)Task-Function:需要执行的任务指针
 


假设当前Current Index指向第一格,当有延时消息到达之后,例如希望3610秒之后,触发一个延时消息任务,只需:
(1)计算这个Task应该放在哪一个slot,现在指向1,3610秒之后,应该是第11格,所以这个Task应该放在第11个slot的Set中
(2)计算这个Task的Cycle-Num,由于环形队列是3600格(每秒移动一格,正好1小时),这个任务是3610秒后执行,所以应该绕3610/3600=1圈之后再执行,于是Cycle-Num=1
 
Current Index不停的移动,每秒移动到一个新slot,这个slot中对应的Set,每个Task看Cycle-Num是不是0:
(1)如果不是0,说明还需要多移动几圈,将Cycle-Num减1
(2)如果是0,说明马上要执行这个Task了,取出Task-Funciton执行(可以用单独的线程来执行Task),并把这个Task从Set中删除
 
使用了“延时消息”方案之后,“订单48小时后关闭评价”的需求,只需将在订单关闭时,触发一个48小时之后的延时消息即可:
(1)无需再轮询全部订单,效率高
(2)一个订单,任务只执行一次
(3)时效性好,精确到秒(控制timer移动频率可以控制精度)
 
四、总结
环形队列是一个实现“延时消息”的好方法,开源的MQ好像都不支持延迟消息,不妨自己实现一个简易的“延时消息队列”,能解决很多业务问题,并减少很多低效扫库的cron任务。

另外,关于MQ的可达性、幂等性未来撰文另述。
 
查看原文:http://www.architecy.com/archives/373
### 设计支持高并发和数据一致性的电商微服务系统 #### 微服务架构下的模块拆分 在设计电商系统的微服务架构时,应遵循单一职责原则和服务自治的原则[^2]。通常可将系统划分为以下几个核心模块:商品管理、库存管理、订单管理、支付管理、用户管理等。每个模块由独立的团队维护并部署,从而提高开发效率和灵活性。 #### 分布式事务处理方案 为了保障跨服务操作的数据一致性,在分布式环境下需采用合适的事务解决方案。常见的方法有两阶段提交(2PC)、补偿事务(TCC)以及基于消息队列的最终一致性方案。其中,TCC因其较低的锁资源消耗而被广泛应用于电商场景中[^4]。 #### 订单超时自动关闭机制实现 对于未完成付款的订单设置合理的有效期非常重要。可以通过定时器或者延迟队列来监控订单状态;一旦超过设定时限仍未收到确认,则触发取消逻辑并将关联的商品重新释放回库存池内。此过程需要注意幂等问题以防止重复执行造成错误扣减或增加可用数量的情况发生。 #### 基于Elasticsearch 的订单搜索模块设计 构建高效的检索能力是提升用户体验的关键之一。利用 Elasticsearch 可快速搭建起全文索引引擎,并针对具体需求调整 mapping 结构与 query DSL 查询语句形式。考虑到实际应用场景中的负载压力测试结果表明适当优化 RestTemplate 调用方式能显著改善响应速度表现[^3]。 关于 ES 索引设计方面,建议按照业务特性定义字段类型及其属性参数配置文件;同时合理规划 primary shard 和 replica 数量分布情况以便平衡读写请求之间的比例关系达到最佳性能水平[^1] 。 ```python from elasticsearch import Elasticsearch es_client = Elasticsearch() def create_index(index_name, mappings): es_client.indices.create(index=index_name, body=mappings) mappings = { "settings": { "number_of_shards": 5, "number_of_replicas": 1 }, "mappings": { "properties": { "order_id": {"type": "keyword"}, "customer_name": {"type": "text", "analyzer":"standard"} } } } create_index('orders', mappings) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值