10w定时任务,如何高效触发超时

简介: 很多时候,业务有定时任务或者定时超时的需求,当任务量很大时,可能需要维护大量的timer,或者进行低效的扫描。

一、缘起

很多时候,业务有定时任务或者定时超时的需求,当任务量很大时,可能需要维护大量的timer,或者进行低效的扫描。

例如:58到家APP实时消息通道系统,对每个用户会维护一个APP到服务器的TCP连接,用来实时收发消息,对这个TCP连接,有这样一个需求:“如果连续30s没有请求包(例如登录,消息,keepalive包),服务端就要将这个用户的状态置为离线”。

其中,单机TCP同时在线量约在10w级别,keepalive请求包大概30s一次,吞吐量约在3000qps。

一般来说怎么实现这类需求呢?

“轮询扫描法”

1)用一个Map来记录每一个uid最近一次请求时间last_packet_time

2)当某个用户uid有请求包来到,实时更新这个Map

3)启动一个timer,当Map中不为空时,轮询扫描这个Map,看每个uid的last_packet_time是否超过30s,如果超过则进行超时处理

“多timer触发法”

1)用一个Map来记录每一个uid最近一次请求时间last_packet_time

2)当某个用户uid有请求包来到,实时更新这个Map,并同时对这个uid请求包启动一个timer,30s之后触发

3)每个uid请求包对应的timer触发后,看Map中,查看这个uid的last_packet_time是否超过30s,如果超过则进行超时处理

方案一:只启动一个timer,但需要轮询,效率较低

方案二:不需要轮询,但每个请求包要启动一个timer,比较耗资源

特别在同时在线量很大时,很容易CPU100%,如何高效维护和触发大量的定时/超时任务,是本文要讨论的问题。

二、环形队列法

废话不多说,三个重要的数据结构:

1)30s超时,就创建一个index从0到30的环形队列(本质是个数组)

2)环上每一个slot是一个Set,任务集合

3)同时还有一个Map,记录uid落在环上的哪个slot里

image.png

同时:

1)启动一个timer,每隔1s,在上述环形队列中移动一格,0->1->2->3…->29->30->0…

2)有一个Current Index指针来标识刚检测过的slot

当有某用户uid有请求包到达时:

1)从Map结构中,查找出这个uid存储在哪一个slot里

2)从这个slot的Set结构中,删除这个uid

3)将uid重新加入到新的slot中,具体是哪一个slot呢 => Current Index指针所指向的上一个slot,因为这个slot,会被timer在30s之后扫描到

(4)更新Map,这个uid对应slot的index值

哪些元素会被超时掉呢?

Current Index每秒种移动一个slot,这个slot对应的Set中所有uid都应该被集体超时!如果最近30s有请求包来到,一定被放到Current Index的前一个slot了,Current Index所在的slot对应Set中所有元素,都是最近30s没有请求包来到的。

所以,当没有超时时,Current Index扫到的每一个slot的Set中应该都没有元素。

优势:

(1)只需要1个timer

(2)timer每1s只需要一次触发,消耗CPU很低

(3)批量超时,Current Index扫到的slot,Set中所有元素都应该被超时掉

三、总结

这个环形队列法是一个通用的方法,Set和Map中可以是任何task,本文的uid是一个最简单的举例。

HashedWheelTimer也是类似的原理,有兴趣的同学可以百度一下这个数据结构,Netty中的一个工具类,希望大家有收获,帮忙转发一下哈。

==【完】==

目录
相关文章
|
新零售 供应链
阿里云电子签:助企业打通业务数字化“最后1公里”
阿里云电子签:助企业打通业务数字化“最后1公里”
2130 3
阿里云电子签:助企业打通业务数字化“最后1公里”
|
5G 网络性能优化 调度
NR 整体架构 | 带你读《5G 空口设计与实践进阶 》之八
每一代移动通信系统,其标志性的技术特征主要在于全新的空口技术。在深入讨论 NR 空中接口的底层设计前,有必要先认识和掌握 NR 无线接口架构。这节主要介绍 NR 的整体架构。
NR 整体架构 | 带你读《5G 空口设计与实践进阶 》之八
|
6月前
|
消息中间件 监控 Kubernetes
别再乱排查了!Kafka 消息积压、重复、丢失,根源基本都是 Rebalance!
大家好,我是小富~分享一次Kafka消息积压排查经历:消费者组因Rebalance导致消费能力骤降。本文详解Rebalance触发场景(消费者变更、分区扩容、订阅变化、超时等),剖析其引发的消息积压、重复消费、丢失等问题根源,并提供优化方案:调优超时参数、手动提交offset、启用粘性分配策略、保障消费幂等性。掌握这些,轻松应对Kafka常见故障!
1178 0
|
Java 数据处理
Java Scanner 类详解
`Scanner` 类是 Java 中 `java.util` 包提供的强大工具,用于从多种输入源(如键盘、文件、字符串)读取数据。本文详细介绍如何创建 `Scanner` 对象并使用其常用方法(如 `next()`, `nextInt()`, `nextLine()` 等)。通过示例代码展示如何从标准输入、字符串及文件中读取数据,并进行输入验证。使用时需注意关闭 `Scanner` 以释放资源,并确保输入类型匹配,避免异常。掌握 `Scanner` 可显著提升程序的数据处理能力。
664 1
|
机器学习/深度学习 PyTorch 算法框架/工具
详解三种常用标准化Batch Norm & Layer Norm & RMSNorm
通过本文的介绍,希望您能够深入理解Batch Norm、Layer Norm和RMSNorm的原理和实现,并在实际应用中灵活选择和使用,提升深度学习模型的性能和稳定性。
3999 5
|
网络协议 网络性能优化 API
TCP或RDMA
【10月更文挑战第1天】TCP或RDMA
872 2
|
安全 JavaScript 前端开发
自动化测试的魔法:如何用Python编写你的第一个测试脚本
【8月更文挑战第41天】在软件的世界里,质量是王道。而自动化测试,就像是维护这个王国的骑士,确保我们的软件产品坚不可摧。本文将引导你进入自动化测试的奇妙世界,教你如何使用Python这把强大的魔法杖,编写出能够守护你代码安全的第一道防护咒语。让我们一起开启这场魔法之旅吧!
|
资源调度 前端开发 JavaScript
前端 nodejs 命令行自动调用编译 inno setup 的.iss文件
前端 nodejs 命令行自动调用编译 inno setup 的.iss文件
|
JavaScript 前端开发 搜索推荐
服务器端渲染技术SSR与ISR:深入解析与应用
【7月更文挑战第20天】服务器端渲染(SSR)和增量静态再生(ISR)作为现代Web开发中的两种重要渲染技术,各有其独特的优势和适用场景。在实际应用中,开发者应根据具体需求和条件选择合适的渲染模式。无论是追求极致的页面加载速度和SEO优化,还是实现内容的实时更新,SSR和ISR都能提供有效的解决方案。通过深入理解这些技术的工作原理和应用场景,开发者可以构建出更加高效、可靠和用户体验优异的Web应用。
|
NoSQL 测试技术 MongoDB
使用同步和异步方式更新插入MongoDB数据的性能对比
在这篇文章中,我将探讨如何使用同步和异步方式插入数据到MongoDB,并对两种方式的性能进行对比。并将通过Python中的 pymongo 和 motor 库分别实现同步和异步的数据插入,并进行测试和分析。

热门文章

最新文章