Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >如何快速实现“延时消息”?

如何快速实现“延时消息”?

作者头像
架构师之路
发布于 2020-05-07 07:37:34
发布于 2020-05-07 07:37:34
1K0
举报
文章被收录于专栏:架构师之路架构师之路

快狗打车订单完成后,如果用户一直不评价,48小时后会将自动评价为5星。

怎么实现这类“48小时后自动评价为5星”需求呢?

画外音:这类“一段时间之后,完成一个任务”的需求很常见。

cron是不是最容易想到的方案?

启动一个cron定时任务,每小时跑一次,将完成时间超过48小时,且仍未评价的订单取出,置为5星,并把评价状态置为已评价。

假设订单表的结构为:

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

更具体的,定时任务每隔一个小时会这么做一次:

select oid from order where finish_time > 48 and status=0;

update order set stars=5 and status=1 where oid in[…];

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

cron方案有什么不足?

(1)轮询效率比较低;

(2)每次扫库,已经被执行过记录,仍然会被扫描(只是不会出现在结果集中),有重复计算的嫌疑;

(3)时效性不够好,如果每小时轮询一次,最差的情况下,时间误差会达到1小时;

(4)如果通过增加cron轮询频率来减少时间误差,则轮询低效和重复计算的问题会进一步凸显;

对于这类需要延时执行的任务,如何保证效率的同时,又保证实时性呢?

答案是:高效延时消息。

高效延时消息,包含两个重要的数据结构

(1)环形队列,例如可以创建一个包含3600个slot的环形队列(本质是个数组);

(2)任务集合,环上每一个slot是一个Set<Task>

同时,启动一个timer

(1)此timer每隔1s,在环形队列中移动一格;

(2)用一个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<Task>中;

(2)计算这个Task的Cycle-Num,由于环形队列是3600格(每秒移动一格,正好1小时),这个任务是3610秒后执行,所以应该绕3610/3600=1圈之后再执行,于是Cycle-Num=1;

Current Index不停的移动,每秒移动一格,当移动到一个新slot,遍历这个slot中对应的Set<Task>,每个Task看Cycle-Num是不是0:

(1)如果不是0,说明还需要多移动几圈,将Cycle-Num减1;

(2)如果是0,说明马上要执行这个Task了,取出Task-Funciton执行,丢给工作线程执行,并把这个Task从Set<Task>中删除;

画外音:注意,不要用timer来执行任务,否则timer会越来越不准。

使用了“延时消息”方案之后,“订单48小时后关闭评价”的需求,只需将在订单关闭时,触发一个48小时之后的延时消息即可:

(1)无需再轮询全部订单,效率高

(2)一个订单,任务只执行一次

(3)时效性好,精确到秒;

画外音:控制timer移动频率可以控制精度。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-04-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 架构师之路 微信公众号,前往查看

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

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

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
每日一博 - 使用环形队列实现高效的延时消息
来个场景: 24小时后将未进行某个Action的业务,执行另外一个动作。 比如 24小时未付款的订单,取消。
小小工匠
2021/08/17
8610
每日一博 - 使用环形队列实现高效的延时消息
如何实现定时推送?
在工作当中遇到了一个需要定时向客户端推送新闻、文章等内容。这个时候在网上搜了很久没有找到合适的解决方案,其实能解决这个问题的方案有很多比如说用到一些大厂贡献的xxMQ中间件之类的,确实能解决问题。但是目前项目比较小根本用不上这么重的框架,在偶然的看到了一位大佬写的文章提供了一个非常不错的思路本篇文章也是受到他的启发实现了之后这里分享给大家。这个大佬的是58的沈剑文章名称是“1分钟实现延迟消息功能”。
JusterZhu
2022/12/07
7800
如何实现定时推送?
架构师如何高效管理1000w+延时任务???(第31讲)
例如:每天1000W订单,PM要求24小时自动5星好评,就可以用延时任务来进行处理。
架构师之路
2025/01/02
920
架构师如何高效管理1000w+延时任务???(第31讲)
领导:谁再用定时任务实现关闭订单,立马滚蛋!
在电商、支付等领域,往往会有这样的场景,用户下单后放弃支付了,那这笔订单会在指定的时间段后进行关闭操作,细心的你一定发现了像某宝、某东都有这样的逻辑,而且时间很准确,误差在1s内;那他们是怎么实现的呢?
做个快乐的码农
2021/12/10
7490
领导:谁再用定时任务实现关闭订单,立马滚蛋!
100行代码实现任务队列
最近刚看完python多线程,为了加深印象,按照1分钟实现“延迟消息”功能的思路,实现了一个简易版的异步队列。
goodspeed
2020/12/25
4540
定时任务高效触发
开发中我们经常会遇到一些需要定时来解决的业务场景。比如,有这样一个需求:“如果连续30s没有请求包(例如登录,消息,keepalive包),服务端就要将这个用户的状态置为离线”。
奋飛
2019/08/14
6420
解决某些有到期时间的场景,不适合定时扫描表来完成处理的情况
一:有一个很大的商品订单表,每天新增数十万条数据。每条数据有个到期时间,需要在到期时间后做一些处理,譬如关闭订单,改变状态之类的。
天涯泪小武
2019/01/17
1.1K0
订单付款倒计时实现方案
 如何实现付款及时呢,首先用户下单后,存储用户的下单时间。下面介绍四种系统自动取消订单的方案:
Java架构师必看
2021/05/14
1.8K0
订单付款倒计时实现方案
订单超时未支付自动关闭的几种实现方案
总结来说,订单超时,非常符合业务有“在一段时间之后,完成一个工作任务”的需求。在这类需求中,许多人第一时间想到的就是用定时任务来实现。
业余草
2020/02/28
13.8K0
RocketMQ进阶-延时消息
在开发中经常会遇到延时任务的需求,例如在12306购买车票,若生成订单30分钟未支付则自动取消;还有在线商城完成订单后48小时不评价 ,自动5星好评。像这类在某事件触发后一段时间内执行的需求任务我们称之为 延时任务。
JAVA日知录
2020/05/26
2.8K0
10w定时任务,如何高效触发超时
一、缘起 很多时候,业务有定时任务或者定时超时的需求,当任务量很大时,可能需要维护大量的timer,或者进行低效的扫描。 例如:58到家APP实时消息通道系统,对每个用户会维护一个APP到服务器的TCP连接,用来实时收发消息,对这个TCP连接,有这样一个需求:“如果连续30s没有请求包(例如登录,消息,keepalive包),服务端就要将这个用户的状态置为离线”。 其中,单机TCP同时在线量约在10w级别,keepalive请求包大概30s一次,吞吐量约在3000qps。 一般来说怎么实现这类需求呢? “轮
架构师之路
2018/03/01
1.7K0
10w定时任务,如何高效触发超时
架构师如何高效管理100w+定时事件???(第30讲)
例如:有100W个用户uid在线接单,客户端每30s会有一个存活上报,如果30s没有上报,服务端要将用户的状态置为不可接单。
架构师之路
2025/01/02
1390
架构师如何高效管理100w+定时事件???(第30讲)
timing-wheel 仿Kafka实现的时间轮算法
从 2 个面试题说起,第一个问题: 如果一台机器上有 10w 个定时任务,如何做到高效触发?
weylan
2021/11/17
1.2K0
手把手实现一条延时消息
近期在维护公司的调度平台,其中有个关键功能那就是定时任务;定时任务大家平时肯定接触的不少,比如 JDK 中的 Timer、ScheduledExecutorService、调度框架 Quartz 等。
crossoverJie
2022/10/27
3370
手把手实现一条延时消息
时间轮在Kafka的实践「建议收藏」
桔妹导读:时间轮是一个应用场景很广的组件,在很多高性能中间件中都有它的身影,如Netty、Quartz、Akka,当然也包括Kafka,本文主要介绍时间轮在kafka的应用和实战,从核心源码和设计的角度对时间轮进行深入的讲解 。
全栈程序员站长
2022/09/27
9200
时间轮在Kafka的实践「建议收藏」
你真的会用延时队列吗(一)
RabbitMQ本身没有直接支持延迟队列功能,但是可以通过以下特性模拟出延迟队列的功能。
用户5397975
2019/10/14
1K0
你真的会用延时队列吗(一)
从零到一实现有趣的时间轮算法,你会了吗!
时间轮(Timing Wheel)是George Varghese和Tony Lauck在1996年的论文【Hashed and Hierarchical Timing Wheels: data structures to efficiently implement a timer facility】实现的,它在Linux内核中使用广泛,是Linux内核定时器的实现方法和基础之一。
小许code
2023/11/08
3.8K2
从零到一实现有趣的时间轮算法,你会了吗!
快速实现一个分布式定时器
作者:刘若愚,腾讯 WXG 后台开发工程师 定时器(Timer)是一种在业务开发中常用的组件,主要用在执行延时通知任务上。本文以笔者在工作中的实践作为基础,介绍如何使用平时部门最常用的组件快速实现一个业务常用的分布式定时器服务。同时介绍了过程中遇到问题的一些解决方案,希望能够给类似场景提供一些解决思路。 1.什么是定时器 定时器(Timer)是一种在指定时间开始执行某一任务的工具(也有周期性反复执行某一任务的Timer,我们这里暂不讨论)。它常常与延迟队列这一概念关联。那么在什么场景下我才需要使用定时
腾讯技术工程官方号
2021/03/30
2.5K0
定时器算法
在日常开发中, 定时任务是一个比较关键的功能。 Java 中一般使用 JDK 中 Timer、ScheduledExecutorService 和调度框架 Quartz等。 通常用于实现延时任务, 周期性任务等, 一般会有两种需求:
leobhao
2022/06/28
1K0
定时器算法
Rust异步浅谈(转)
这篇文章主要描述了Rust中异步的原理与相关的实现,Rust异步也是在最近的版本(1.39)中才稳定下来。希望可以通过这边文章在提高自己认知的情况下,也可以给读者带来一些解惑。(来自于本人被Rust异步毒打的一些经验之谈).
8菠萝
2021/07/09
7730
相关推荐
每日一博 - 使用环形队列实现高效的延时消息
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档