时间轮-理论篇

简介: 定时任务再开发过程中无处不在,定时发送消息,定时更新数据库表的状态,Linux系统定时执行脚本等等。这些操作都离不开定时任务,那么这些定时任务是怎么实现的是否又去想过。如果让开发者自己去实现一个定时任务又该怎么实现?时间轮

1. 引言

定时任务再开发过程中无处不在,定时发送消息,定时更新数据库表的状态,Linux系统定时执行脚本等等。这些操作都离不开定时任务,那么这些定时任务是怎么实现的是否又去想过。如果让开发者自己去实现一个定时任务又该怎么实现?

最简单的方案:定义一个链表,将要执行的任务添加到链表中。然后用线程去遍历链表,找出需要执行的任务进行执行。通过反复遍历任务链表就能实现定时任务的执行功能。

定时任务简单实现

但是上述方案有一个很重要的缺陷:如果我的任务有上百万个甚至更多的情况下,可能光遍历整个链表找出需要执行的任务就要花费一定量的时间。如果此时刚好有一个任务添加到链表的Tail,但是任务扫描的指针此时刚好在第一个Head任务节点。此时添加的任务执行时间就在添加后的20ms后,这个时候线程扫描到最后一个需要执行的任务的耗时可能超过了20ms,那么这种情况下就会出现任务的延迟执行。

Tips: 任务的延迟执行需要有一个合理的容忍范围。

在论文《Hashed and Hierarchical Timing Wheels》 提出了时间轮的概念来解决传统定时任务中的弊端

2. 时间轮简介

在生活中大家肯定见过指针手表(非电子手表)这个就可以看做时间轮,山地自行车的前后齿轮、水表的齿轮、以及减速齿轮都可以看做是时间轮。以手表的刻度为例子,机械手表上最长的指针每条以下表示1秒,也就是将一分钟分成了60个1秒。 时间轮的核心思想:将单位时间分成若干个时间间隔,每个时间间隔包含了时间单位除以若干时间间隔的时间量,时间轮转动到对应的时间间隔就执行当前时间间隔对应的可执行的任务。

下面用例子来说明:

1秒我们可以分成8个时间间隔,那么每个时间间隔就是125ms,如下图所示:

2.1 简单的时间轮

在论文《Hashed and Hierarchical Timing Wheels》 中每一个时间间隔叫做 bucket 。 bucket的作用用于存放当前时间间隔内存在的需要执行的任务。例如现在有四个任务A、B、C、D分别要在一秒的三个不同的时间段执行,A、B在两个不同的时间段执行,C、D在同一个时间段执行。那么在时间轮上的示意图如下:

简单时间轮示意图

当时间轮的指针从1Bucket的开始时间到结束时间段的过程中,会去遍历Bucket的链表中的任务,将需要执行的任务从链表中拿出来执行。已上图的例子每一秒时间轮的指针走一圈。

Tips: bucket中存放的任务是时间轮一个时间间隔中的任务,也就是说这些任务是一个时间段里面的任务。例如:100ms和80ms需要执行的任务都说存在bucket1。

进一步思考,如果你一分钟执行一次,那么时间轮的刻度就需要分成480个时间段,随着单位时间刻度的增加会让时间论的刻度越来越多。这样对于计算机来说就是消耗更多的内存。这种如何解决,在论文中提出另一个概念就是:分层时间轮

2.2 分层时间轮

在生活中分层时间轮也是比比皆是,例如在手表长最长的指针代表秒针,中间的代表分针,最短的代表时针。例如我有三个任务 A、B、C分别在以下时间执行:

  • A六十秒的时候执行一次
  • B十五分钟的时候执行一次
  • C六点位置的时候执行一次

如下图所示:

分层时间轮执行示意图

秒时间轮完成一圈触发分时间轮刻度往下一个,分时间轮完成一周触发时时间轮往下一个刻度。分层时间轮之间的刻度关系可以自己定义。不需要和时间刻度表上一样的。具体取决于业务的需要。例如:Linux的Corntab只支持分钟,而Java的Quartz可以支持到秒。

3.总结

时间轮是一种高效来利用线程资源来进行批量化调度的一种调度模型。提高利用率,但是时间轮调度器的时间精度可能不是很高,对于精度要求特别高的调度任务可能不太适合。因为时间轮算法的精度取决于,也就是时间间隔,时间间隔越小精度越高。时间轮的使用在各大框架与中间件中有使用,netty,kafka,jraft(这个是fork netty的)。

我是蚂蚁背大象,文章对你有帮助点赞关注我,文章有不正确的地方请您斧正留言评论~谢谢!
相关文章
|
6月前
|
机器学习/深度学习 算法 搜索推荐
【解密算法:时间与空间的博弈】(中)
【解密算法:时间与空间的博弈】
|
6月前
|
存储 算法
【解密算法:时间与空间的博弈】(上)
【解密算法:时间与空间的博弈】
|
6月前
R语言解释生存分析中危险率和风险率的变化
R语言解释生存分析中危险率和风险率的变化
|
6月前
|
存储 算法 编译器
【解密算法:时间与空间的博弈】(下)
【解密算法:时间与空间的博弈】
|
缓存 算法 Cloud Native
面试技巧:如何在有限时间内优化代码性能
面试技巧:如何在有限时间内优化代码性能
70 0
|
缓存 Kubernetes 负载均衡
K8s有损发布问题探究
应用发布过程往往出现流量有损,本次文章内容通过提出问题、问题分析和解决方案,EDAS在面对上述问题时,提供了无侵入式的解决方案,无需更改程序代码或参数配置,在EDAS控制台即可实现应用无损上下线。
1050 10
K8s有损发布问题探究
|
安全 Java Linux
正确认识及掌握时间的用法
时间是一个相对地区而言的概念,因此有一个基准地区,就是本初子午线穿过的地区。了解世界时间相关的概念可以更好地协调全球人们的活动,便于跨越不同地区的时差。比如按照UTC时区划分算,洛杉矶和北京 之间的时间差异是16个小时, 但是一旦洛杉矶启用了夏令时两者之间的时间差异只有15个小时,神奇吗?
322 0
正确认识及掌握时间的用法
|
缓存 Kubernetes 负载均衡
K8s 有损发布问题探究
下文将通过对 EDAS 客户真实场景的归纳,从 K8s 的流量路径入手,分析有损发布产生的原因,并提供实用的解决方案。
K8s 有损发布问题探究
|
算法 Java C++
算法系统学习-水仙fa数是啥花?(蛮力算法补充)
该系列是基于有一定语言基础(C,C++,Java等等)和基本的数据结构基础进行的算法学习专栏,如果觉得有点吃力 😥 ,建议先了解前提知识再学习喔!本个专栏会将用更容易理解的表达去学习算法,如果在一些表述上存在问题还请各位多多指点
151 0