- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
承接之前的【精华推荐 |【算法数据结构专题】「延时队列算法」史上非常详细分析和介绍如何通过时间轮(TimingWheel)实现延时队列的原理指南】,让我们基本上已经知道了「时间轮算法」原理和核心算法机制,接下来我们需要面向于实战开发以及落地角度进行分析如何实现时间轮的算法机制体系.
相比传统的队列形式的调度器来说,时间轮能够批量高效的管理各种延时任务、周期任务、通知任务等等。例如延时队列/延时任务体系 。
**延时任务、周期性任务,应用场景主要在延迟大规模的延时任务、周期性的定时任务等.
比如,对于耗时的网络请求( 比如Produce时等待ISR副本复制成功 )会被封装成DelayOperation进行延迟处理操作,防止阻塞Kafka请求处理线程,从而影响效率和性能.
Kafka没有使用传统的队列机制(JDK自带的Timer+DelayQueue实现)。因为 时间复杂度 上这两者插入和删除操作都是 O(logn),不能满足Kafka的高性能要求.
JDK Timer和DelayQueue底层都是个优先队列,即采用了minHeap的数据结构,最快需要执行的任务排在队列第一个,不一样的是Timer中有个线程去拉取任务执行,DelayQueue其实就是个容器,需要配合其他线程工作.
ScheduledThreadPoolExecutor是JDK的定时任务实现的一种方式,其实也就是DelayQueue+池化线程的一个实现 .
时间轮算法的插入删除操作都是O(1)的时间复杂度,满足了Kafka对于性能的要求。除了Kafka以外,像 Netty 、ZooKeepr、Dubbo等开源项目、甚至Linux内核中都有使用到时间轮的实现.
当流量小时,使用DelayQueue效率更高。当流量大事,使用时间轮将大大提高效率.
数据结构模型主要由:时间轮环形队列和时间轮任务列表组成.
时间轮(TimingWheel) 是一个存储定时任务的 环形队列(cycle array) ,底层采用环形数组实现,数组中的每个元素可以对应一个 时间轮任务任务列表(TimeWheelTaskList) .
时间轮任务任务列表(TimeWheelTaskList) 是一个环形的双向链表,其中的每个元素都是延时/定时任务项(TaskEntry),其中封装了任务基本信息和元数据(Metadata).
可以看到图中的几个参数:
startMs: 开始时间 。
tickMs: 时间轮执行的最小单位 。 时间轮 由多个时间格组成,每个 时间格 代表当前时间轮的基本时间跨度就是tickMs.
wheelSize: 时间轮中环形队列的数量 。 时间轮 的时间格数量是固定的,可用wheelSize来表示.
interval: 时间轮的整体时间跨度 = tickMs * wheelSize 。
根据上面这两个属性,我们就可以讲整个时间轮的总体时间跨度(interval)可以通过公式tickMs × wheelSize计算得出。例如果时间轮的 tickMs=1ms , wheelSize=20 ,那么可以计算得出interval为 20ms .
此外,时间轮还有一个游标指针,我们称之为(currentTime),它用来表示时间轮当前所处的时间,currentTime是tickMs的整数倍.
整个时间轮的总体跨度是不变的,随着指针currentTime的不断流动,当前时间轮所能处理的时间段也在不断后移,整个时间轮的时间范围在currentTime和currentTime+interval之间.
currentTime可以将整个时间轮划分为到期部分和未到期部分,currentTime当前指向的时间格也属于到期部分,表示刚好到期,需要处理此时间格所对应的TimeWheelTaskList中的所有任务.
初始情况下表盘指针currentTime指向时间格0,此时有一个定时为2ms的任务插入进来会存放到时间格为2的任务列表中.
随着时间的不断推移,指针currentTime不断向前推进,过了2ms之后,当到达时间格2时,就需要将时间格2所对应的任务列表中的任务做相应的到期操作.
此时若又有一个定时为8ms的任务插入进来,则会存放到时间格10中,currentTime再过8ms后会指向时间格10.
总之,整个时间轮的总体跨度是不变的,随着指针currentTime的不断推进,当前时间轮所能处理的时间段也在不断后移,总体时间范围在currentTime和currentTime+interval之间 .
如果当提交了超过整体跨度(interval)的延时任务,如何解决呢?因此引入了层级时间轮的概念,当任务的到期时间超过了当前时间轮所表示的时间范围时,就会尝试添加到层次时间轮中.
在任务插入时,如果第一层时间轮不满足条件,就尝试插入到高一层的时间轮,以此类推.
第一层的时间轮tickMs=1ms, wheelSize=20, interval=20ms 。
第二层的时间轮的tickMs为第一层时间轮的interval,即为20ms 。
第一层和第二层时间轮的wheelSize是固定的,都是20,那么第二层的时间轮的总体时间跨度interval为400ms。正好是第一层时间轮的20倍。 以此类推,这个400ms也是第三层的tickMs的大小,第三层的时间轮的总体时间跨度为8000ms .
随着时间推进,也会有一个时间轮降级的操作,原本延时较长的任务会从高一层时间轮重新提交到时间轮中,然后会被放在合适的低层次的时间轮当中等待处理; 。
例如:350ms的定时任务,显然第一层时间轮不能满足条件,所以就升级到第二层时间轮中,最终被插入到第二层时间轮中时间格17所对应的TimeWheelTaskList中。如果此时又有一个定时为450ms的任务,那么显然第二层时间轮也无法满足条件,所以又升级到第三层时间轮中,最终被插入到第三层时间轮中时间格1的TimeWheelTaskList中.
在 [400ms,800ms) 区间的多个任务(比如446ms、455ms以及473ms的定时任务)都会被放入到第三层时间轮的时间格1中,时间格1对应的TimerTaskList的超时时间为400ms 。
随着时间的流逝,当次TimeWheelTaskList到期之时,原本定时为450ms的任务还剩下50ms的时间,还不能执行这个任务的到期操作.
这里就有一个时间轮降级的操作,会将这个剩余时间为50ms的定时任务重新提交到层级时间轮中,此时第一层时间轮的总体时间跨度不够,而第二层足够,所以该任务被放到第二层时间轮到期时间为[40ms,60ms)的时间格中.
再经历了40ms之后,此时这个任务又被“察觉”到,不过还剩余10ms,还是不能立即执行到期操作。所以还要再有一次时间轮的降级,此任务被添加到第一层时间轮到期时间为[10ms,11ms)的时间格中,之后再经历10ms后,此任务真正到期,最终执行相应的到期操作.
接下来小编会出【算法数据结构专题】「延时队列算法」史上手把手教你针对层级时间轮(TimingWheel)实现延时队列的开发实战落地(下),进行实战编码进行开发对应的层次化的时间轮算法落地.
最后此篇关于【算法数据结构专题】「延时队列算法」史上手把手教你针对层级时间轮(TimingWheel)实现延时队列的开发实战落地(上)的文章就讲到这里了,如果你想了解更多关于【算法数据结构专题】「延时队列算法」史上手把手教你针对层级时间轮(TimingWheel)实现延时队列的开发实战落地(上)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
与其他许多不同,Coq 接受一个可选的显式参数,该参数可用于指示固定点定义的递减结构。 从 Gallina 规范,1.3.4, Fixpoint ident params {struct ident0
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
前言:我目前正在学习 ANN,因为我在大约 83 个类别中有大约 18500 张图像。它们将用于训练 ANN 以实时识别大致相等的图像。我按照书中的图像示例进行操作,但它对我不起作用。所以我要回到开头
在我的程序中,我处理有时为 NULL 的 C 风格字符串(类型为 char *)。我想教 cout 优雅地处理这些问题(即打印“(null)”而不是段错误)。 我的第一次尝试: ostream& op
我正在开发一个采用(定制的)微线程解决方案的大型程序。有时我需要调试崩溃。在这种时候,能够从一个微线程切换到另一个微线程是很有用的。 如果我正在进行实时调试,我可以将所有寄存器替换为来自微线程上下文的
我可以教 Notepad++ 在它看到多行注释时应用折叠,其中注释以井号开头,多行注释是连续行上的井号吗? # This is a comment # It continues on the next
我被要求为一个 child 辅导 Pascal。尽管在我设法获得教程之前从未见过 Pascal,但我现在知道的足以教他了。 我给你们写信是想看看是否有人能给我指出一些涉及简单算法的基本练习,比如:对这
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我正在维护来自外国情报监视法庭的大量编辑文件的文件。 它们带有大段文本,如下所示: 当 OCR 尝试处理此问题时,您会收到如下文本: production of this data on a dail
今年夏天,我将教高中生使用 C++ 编程。我必须在一周内教给他们 Material 。通读了公司给我的教程,他们建议我一开始就在程序中使用“include stdafx.h”。 你觉得呢 includ
我需要在他的笔记本电脑上安装一个 c# ide(免费),我需要下载 sdk 还是 windows 7 带有 c# 编译器? (从头开始设置已经有一段时间了) 最佳答案 你可以试试Visual C# 2
背景 我刚刚在 AWS 上启动了一个新的 Redshift 实例,我可以毫无问题地通过 psql cli 客户端连接到它。 问题 我正在尝试让我的 Rails 3 应用程序连接到 Redshift 盒
我是一名优秀的程序员,十分优秀!