Kafka时间轮(TimerWheel)--算法简介

news2024/9/22 5:29:05

一、简介

一个简单的时间轮是一个定时器任务桶的循环列表。

  1. 让u作为时间单位。
  2. 尺寸为n的时间轮有n个桶,可以在n*u的时间间隔内保存定时器任务。
  3. 每个bucket保存属于相应时间范围的计时器任务。

在开始时,

  1. 第一个桶保存[0,u)的任务,第二个桶保存[u,2u),…的任务…,[u*(n-1),u*n)的第n个bucket。
  2. 每个时间单位u的间隔,计时器滴答作响移动到下一个bucket,然后使其中的所有计时器任务过期。

因此,计时器从不插入任务到当前时间的存储桶,因为它已经过期

计时器会立即运行已过期的任务。清空的bucket可用于下一轮,因此如果当前为时间t的bucket,它在一个tick之后变成[t+u*n,t+(n+1)*u)的bucket。

二、时间轮复杂度分析 

  • 时间轮的插入/删除(启动定时器/停止定时器)成本为O(1)
  • 优先级队列基于定时器,如java.util.concurrent.DelayQueue和java.util.Timer,具有O(logn)插入/删除成本。

三、简单时间轮

简单时间轮的一个主要缺点是,它假设计时器请求在从当前时间开始的n*u的时间间隔。
如果定时器请求超出该间隔,会产生溢出。

四、分级时间轮

  1. 分级时间轮会处理上面这种溢出,这是一种等级制度有组织的时间轮。
  2. 最低级别的时间分辨率最好。随着向上移动层次结构,时间分辨率变得更粗糙。
  3. 如果一个轮子在一个级别上的分辨率是u并且大小为n,下一级的分辨率应为n*u。
  4. 在每个级别上,溢出为委托给更高一级的轮子。
  5. 当较高级别的轮子发出滴答声时,它会重新插入计时器任务到较低级别。
  6. 溢流轮可以按需创建。当一个桶溢出存储桶过期,其中的所有任务都会递归地重新插入计时器。
  7. 这些任务会被移动到更细粒度的轮子或被执行。插入(启动计时器)成本为O(m),其中m是轮子的数量,与请求的数量相比,这个数量通常很小,并且删除(停止定时器)成本仍然是O(1)

https://imgconvert.csdnimg.cn/aHR0cHM6Ly9tbWJpei5xcGljLmNuL21tYml6X3BuZy8xd0JaQ0dpYVlxQkc4ZmlhSDVEcGNYbDRnWDlkU0poRnpGWHpkZWczUVVnZG9KMjZSdFlRcGliRnNGSzBJWGhpY285eGljUHNaRHZSblljaWNxdWw1N1AwdFAwZy82NDA?x-oss-process=image/format,png

五、示例

假设u是1,n是3。如果开始时间是c,则不同级别的桶是:

时间轮层级bucket
1[c,c][c+1,c+1][c+2,c+2]
2[c,c+2][c+3,c+5][c+6,c+8]
3[c,c+8][c+9,c+17][c+18,c+26]

前序bucket到期时间为后序bucket开始时间。

  1. 因此,在时间=c+1时,存储桶[c,c]、[c,c+2]和[c,c+8]到期。
  2. 级别1的时钟移动到c+1,并创建[c+3,c+3]。
  3. 级别2和级别3的时钟保持在c,因为它们的时钟分别以3和9为单位移动。因此,在级别2和级别3中不会创建新的bucket

注意,级别2中的bucket[c,c+2]不会接收任何任务,因为该范围已经在级别1中涵盖。
级别3中的bucket[c,c+8]也是如此,因为它的范围在级别2中涵盖。

这有点浪费,但简化了实现。

时间轮层级bucket
1[c+1,c+1][c+2,c+2][c+3,c+3]
2[c,c+2][c+3,c+5][c+6,c+8]
3[c,c+8][c+9,c+17][c+18,c+26]

在时间=c+2时,[c+1,c+1]是新到期的, 级别1移动到c+2,并创建[c+4,c+4],

时间轮层级bucket
1[c+2,c+2][c+3,c+3][c+4,c+4]
2[c,c+2][c+3,c+5][c+6,c+8]
3[c,c+8][c+9,c+17][c+18,c+26]

    

在时间=c+3时,[c+2,c+2]是新到期的; 级别2移动到c+3,并创建[c+5,c+5]和[c+9,c+11]。
3级停留在c。

时间轮层级bucket
1[c+3,c+3][c+4,c+4][c+5,c+5]
2[c+3,c+5][c+6,c+8][c+9,c+11]
3[c,c+8][c+9,c+17][c+18,c+26]

当操作在超时之前完成时,分级正时轮工作得特别好。即使一切都超时了,当计时器中有很多项目时,它仍然具有优势。其插入成本(包括重新插入)和删除成本分别为O(m)O(1),而优先级为基于队列的计时器为插入和删除取O(log N),其中N是队列中的项目数。

============================= 英文版  ================================== 


Hierarchical Timing Wheels

A simple timing wheel is a circular list of buckets of timer tasks. Let u be the time unit.
A timing wheel with size n has n buckets and can hold timer tasks in n * u time interval.
Each bucket holds timer tasks that fall into the corresponding time range. At the beginning,
the first bucket holds tasks for [0, u), the second bucket holds tasks for [u, 2u), …,
the n-th bucket for [u * (n -1), u * n). Every interval of time unit u, the timer ticks and
moved to the next bucket then expire all timer tasks in it. So, the timer never insert a task
into the bucket for the current time since it is already expired. The timer immediately runs
the expired task. The emptied bucket is then available for the next round, so if the current
bucket is for the time t, it becomes the bucket for [t + u * n, t + (n + 1) * u) after a tick.
A timing wheel has O(1) cost for insert/delete (start-timer/stop-timer) whereas priority queue
based timers, such as java.util.concurrent.DelayQueue and java.util.Timer, have O(log n)
insert/delete cost.

A major drawback of a simple timing wheel is that it assumes that a timer request is within
the time interval of n * u from the current time. If a timer request is out of this interval,
it is an overflow. A hierarchical timing wheel deals with such overflows. It is a hierarchically
organized timing wheels. The lowest level has the finest time resolution. As moving up the
hierarchy, time resolutions become coarser. If the resolution of a wheel at one level is u and
the size is n, the resolution of the next level should be n * u. At each level overflows are
delegated to the wheel in one level higher. When the wheel in the higher level ticks, it reinsert
timer tasks to the lower level. An overflow wheel can be created on-demand. When a bucket in an
overflow bucket expires, all tasks in it are reinserted into the timer recursively. The tasks
are then moved to the finer grain wheels or be executed. The insert (start-timer) cost is O(m)
where m is the number of wheels, which is usually very small compared to the number of requests
in the system, and the delete (stop-timer) cost is still O(1).

Example
Let's say that u is 1 and n is 3. If the start time is c,
then the buckets at different levels are:

level    buckets
1        [c,c]   [c+1,c+1]  [c+2,c+2]
2        [c,c+2] [c+3,c+5]  [c+6,c+8]
3        [c,c+8] [c+9,c+17] [c+18,c+26]

The bucket expiration is at the time of bucket beginning.
So at time = c+1, buckets [c,c], [c,c+2] and [c,c+8] are expired.
Level 1's clock moves to c+1, and [c+3,c+3] is created.
Level 2 and level3's clock stay at c since their clocks move in unit of 3 and 9, respectively.
So, no new buckets are created in level 2 and 3.

Note that bucket [c,c+2] in level 2 won't receive any task since that range is already covered in level 1.
The same is true for the bucket [c,c+8] in level 3 since its range is covered in level 2.
This is a bit wasteful, but simplifies the implementation.

1        [c+1,c+1]  [c+2,c+2]  [c+3,c+3]
2        [c,c+2]    [c+3,c+5]  [c+6,c+8]
3        [c,c+8]    [c+9,c+17] [c+18,c+26]

At time = c+2, [c+1,c+1] is newly expired.
Level 1 moves to c+2, and [c+4,c+4] is created,

1        [c+2,c+2]  [c+3,c+3]  [c+4,c+4]
2        [c,c+2]    [c+3,c+5]  [c+6,c+8]
3        [c,c+8]    [c+9,c+17] [c+18,c+26]

At time = c+3, [c+2,c+2] is newly expired.
Level 2 moves to c+3, and [c+5,c+5] and [c+9,c+11] are created.
Level 3 stay at c.

1        [c+3,c+3]  [c+4,c+4]  [c+5,c+5]
2        [c+3,c+5]  [c+6,c+8]  [c+9,c+11]
3        [c,c+8]    [c+9,c+17] [c+18,c+26]

The hierarchical timing wheels works especially well when operations are completed before they time out.
Even when everything times out, it still has advantageous when there are many items in the timer.
Its insert cost (including reinsert) and delete cost are O(m) and O(1), respectively while priority
queue based timers takes O(log N) for both insert and delete where N is the number of items in the queue.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/465398.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第7章 “字典”

1.字典简介 字典是什么? 解答:与集合类似,也是一种存储唯一值的数据结构,但它是以键值对的形式来存储。(键值对是最重要的特性)在Es6中新增了字典,名为Map字典的常用操作:增删改查 const map new Map()/…

使用PY003基于外部中断+定时器的方式实现NEC红外解码

写在前边 最近项目用到一款遥控器是38K红外载波,NEC协议的,找了很多帖子有看到用外部中断下降沿判断(但可惜判定数据的方式是while在外部中断里面死等的),有看到用100us定时器定时刷来判断,感觉都不太适合用在我这个工…

基于MATLAB实现WSN(无线传感器网络)的LEACH(低能耗自适应集群层次结构)(Matlab代码实现)

目录 💥1 概述 📚2 运行结果 🎉3 参考文献 👨‍💻4 Matlab代码 💥1 概述 低能耗自适应集群层次结构(“LEACH”)是一种基于 TDMA 的 MAC 协议,它与无线传感器网络 &a…

[2018.09.25][Sourceinsight]4.0配置

1 字体放大 (1)panel fonts: option,preference,colors&font (2)code fonts: option,file type options 2 修改默认字体 Alt y 3 显示行号 点击菜单栏View->Line Numbers 4 破解 https://blog.csdn.net/biubiuibiu/article/details/78044232 5 全局搜索字…

在Spring Boot微服务使用knife4j发布后端API接口

记录:422 场景:在Spring Boot微服务上,应用knife4j发布后端API接口,辅助开发与调试。 版本:JDK 1.8,Spring Boot 2.6.3,knife4j-3.0.3,springfox-swagger2-3.0.0。 Knife4j: 是一个集Swagger2 和 OpenAPI3为一体的增…

第三十二篇,记一次Windows下Qt使用boost的经历

Win10系统 Qt版本如下所示 Qt中使用的编译器是MinGW,如下图 boost版本是1.82.0 好的,描述一下过程: 按这个教程下载、编译boost,在boost的目录下生成了stage/lib/目录,然后加入到Qt工程里,主要是include目…

win10安装Anaconda,配置Pytorch环境

一、安装Anaconda Anaconda实际上是一个包管理器,可以理解为一个工具。Anaconda自带Python(选中版本)解释器以及其他一些数据分析与挖掘需要的模块而无需用户手动添加这些常用模块(安装模块会出现各种错误)。早期学Pyt…

Django个性化推荐系统,以电影为例

背景 随着科学技术发展,电脑已成为人们生活中必不可少的生活办公工具,在这样的背景下,网络技术被应用到各个方面,为了提高办公生活效率,网络信息技术飞速发展。在这样的背景下人类社会进入了全新的信息化的时代。电影…

flask+opencv:实时视频直播推流平台Demo

简介:推流,指的是把采集阶段封包好的内容传输到服务器的过程。其实就是将现场的视频信号传到网络的过程。网上调查、对话访谈、在线培训等内容现场发布到互联网上。利用互联网的直观、快速,表现形式好、内容丰富、交互性强、地域不受限制、受…

华为OD机试真题(Java),猴子爬山(100%通过+复盘思路)

一、题目描述 一天一只顽猴想去从山脚爬到山顶,途中经过一个有个N个台阶的阶梯,但是这猴子有一个习惯: 每一次只能跳1步或跳3步,试问猴子通过这个阶梯有多少种不同的跳跃方式? 二、输入描述 输入只有一个整数N&…

AI语音生成器是下一大安全威胁吗?

ChatGPT一经上市,有关监管人工智能的讨论就开始升温。任何试图遏制这种技术的做法都可能需要国际合作,需要我们在过去几十年来从未见过的合作程度,因此不太可能遏制人工智能。 人工智能是一项功能强大的技术,有望彻底改变我们生活…

AIGC - 生产力新工具 Bito AI

文章目录 Bito AI 是什么Bito AI 能干啥官网免费的吗?如何使用 Bito方式一:方式二:在这里插入图片描述方式三 Bito AI 是什么 Bito AI是继Github Copilot、Cursor、CodeWhisperer等AI智能编程产品之后发了一大AI编程工具 。 Bito是一款建立…

表情迁移 - 2D人像动起来(附带生成web服务提供api接口)

左边原图,右边是渲染后的视频文件 开源地址:https://github.com/AliaksandrSiarohin/first-order-model 官方模型下载地址(需科学上网): google-driveyandex-disk本文docker容器已自带人脸模型 若还需要行为、物品、动画等追踪模型需下载后拷贝至容器内即可使用 API请求…

Android之 Camera相机使用

一 简介 1.1 随着信息时代的发展,相机在我们生活中使用越来越频繁,也成为手机的基本配置之一。相机可以用来拍照,拍视频,人脸识别,视频聊天,扫码支付,监控等常见领域 不管什么场景&#xff0c…

DolphinScheduler 2.0.5详解

文章目录 第一章 DolphinScheduler介绍1.1 关于DolphinScheduler1.2 DolphinScheduler特性1.3 配置建议1.3.1 Linux 操作系统版本要求1.3.2 服务器建议配置1.3.3 生产环境1.3.4 网络要求1.3.5 客户端 Web 浏览器要求 第二章 DolphinScheduler安装部署2.1 安装部署介绍2.2 单机版…

Mybatis笔记分享【狂神说java】

MyBatis 1、简介 1.1什么是MyBatis MyBatis 是一款优秀的持久层框架 它支持自定义 SQL、存储过程以及高级映射 MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作 MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(…

Windows环境下使用Internet Information Service( IIS)管理器上搭建Web资源网站

一、业务需求 在项目的开发过程中,需要将指定文件夹发布称为一个网站,可以通过网页查看该文件夹下的内容和子目录(及其子目录内容);同时也可以将内容上传到该文件夹中,方便他人使用,如下图所示: 二、思路分析 将文件夹发布为网站,可以使用Windows的IIS管理器搭建一个W…

Scala之模式匹配与隐式转换

目录 模式匹配: 基础语法如下: 模式守卫: 类型匹配: 对象匹配 样例类: 偏函数: 偏函数的化简写法: 偏函数的使用: 隐式转换: 官方定义: 个人理解&…

(小甲鱼python)文件永久存储(下)总结 文件处理with语句和上下文管理器、pickle模块详解

一、基础复习 上节课回顾: 1.文件永久存储(上) python文件永久存储(创建打开文件、文件对象的各种方法及含义) 2.文件永久存储(中)总结 路径处理 pathlib–面向对象的文件系统路径 绝对路径vs相对路径(路径查询、路径修改、查找功能) 二、文…

【JavaScript】new命令精华总结

相关概念 对象是什么? 1.对象是单个实物的抽象 2.对象是一个容器,封装了属性和方法 属性是对象的状态,方法是对象的行为,把对象中的函数一般称为方法 构造函数 专门用来生成实例对象的函数,是对象的模板,第一个字…