解惑“高深”的Kafka时间轮原理,原来也就这么回事!
【摘要】 Kafka时间轮是Kafka实现高效的延时任务的基础,它模拟了现实生活中的钟表对时间的表示方式,同时,时间轮的方式并不仅限于Kafka,它是一种通用的时间表示方式,本文主要介绍Kafka中的时间轮原理。
Kafka中存在一些定时任务(DelayedOperation),如DelayedFetch、DelayedProduce、DelayedHeartbeat等,在Kafka中,定时任务的添加、轮转、执行、消亡等是通过时间轮来实现的。(时间轮并不是Kafka独有的设计,而是一种通用的实现方式,Netty中也有用到时间轮的方式)
1. 时间轮是什么
参考网上的两张图(摘自 https://blog.csdn.net/u013256816/article/details/80697456)


这两张图就比较清楚的说明了Kafka时间轮的结构了:类似现实中的钟表,由多个环形数组组成,每个环形数组包含20个时间单位,表示一个时间维度(一轮),如:第一层时间轮,数组中的每个元素代表1ms,一圈就是20ms,当延迟时间大于20ms时,就“进位”到第二层时间轮,第二层中,每“一格”表示20ms,依此类推…
对于一个延迟任务,大体包含三个过程:进入时间轮、降级和到期执行。
- 进入时间轮
1. 根据延迟时间计算对应的时间轮“层次”(如钟表中的“小时级”还是“分钟级”还是“秒级”,实际上是一个不断“升级”的过程,直到找到合适的“层次”)
2. 计算在该轮中的位置,并插入该位置(每个bucket是一个双向链表,可能包含多个延迟任务,这也是时间轮提高效率的一大原因,后面会提到)
3. 若该bucket是首次插入,需要将该bucket加入DelayQueue中(DelayQueue的引入是为了解决“空推进”,后面会提到)

- 降级
1. 当时间“推进”到某个bucket时,说明该bucket中的任务在当前时间轮中的时间已经走完,需要进行“降级”,即进入更小粒度的时间轮中,reinsert的过程和进入时间轮是类似的

- 到期执行
1. 在reinsert的过程中,若发现已经到期,则执行这些任务

整体过程大致如下:

2. 时间的“推进”
一种直观的想法是,像现实中的钟表一样,“一格一格”地走,这样就需要有一个线程一直不停的执行,而大多数情况下,时间轮中的bucket大部分是空的,指针的“推进”就没有实质作用,因此,为了减少这种“空推进”,Kafka引入了DelayQueue,以bucket为单位入队,每当有bucket到期,即queue.poll能拿到结果时,才进行时间的“推进”,减少了 ExpiredOperationReaper 线程空转的开销。

3. 为什么要用时间轮
用到延迟任务时,比较直接的想法是DelayQueue、ScheduledThreadPoolExecutor 这些,而时间轮相比之下,最大的优势是在时间复杂度上:
时间复杂度对比:

因此,理论上,当任务较多时,TimingWheel的时间性能优势会更明显
总结一下Kafka时间轮性能高的几个主要原因:
(1)时间轮的结构+双向列表bucket,使得插入操作可以达到O(1)的时间复杂度
(2)Bucket的设计让多个任务“合并”,使得同一个bucket的多次插入只需要在delayQueue中入队一次,同时减少了delayQueue中元素数量,堆的深度也减小,delayqueue的插入和弹出操作开销也更小
解惑“高深”的Kafka时间轮原理,原来也就这么回事!的更多相关文章
- kafka时间轮的原理(一)
概述 早就想写关于kafka时间轮的随笔了,奈何时间不够,技术感觉理解不到位,现在把我之前学习到的进行整理一下,以便于以后并不会忘却.kafka时间轮是一个时间延时调度的工具,学习它可以掌握更加灵活先 ...
- kafka时间轮简易实现(二)
概述 上一篇主要介绍了kafka时间轮源码和原理,这篇主要介绍一下kafka时间轮简单实现和使用kafka时间轮.如果要实现一个时间轮,就要了解他的数据结构和运行原理,上一篇随笔介绍了不同种类的数据结 ...
- [从源码学设计]蚂蚁金服SOFARegistry之时间轮的使用
[从源码学设计]蚂蚁金服SOFARegistry之时间轮的使用 目录 [从源码学设计]蚂蚁金服SOFARegistry之时间轮的使用 0x00 摘要 0x01 业务领域 1.1 应用场景 0x02 定 ...
- 精华推荐 |【算法数据结构专题】「延时队列算法」史上非常详细分析和介绍如何通过时间轮(TimingWheel)实现延时队列的原理指南
时间轮的介绍 时间轮(TimeWheel)是一种实现延迟功能(定时器)的精妙的高级算法,其算法应用范围非常广泛,在Java开发过程中常用的Dubbo.Netty.Akka.Quartz.ZooKeep ...
- Kafka中时间轮分析与Java实现
在Kafka中应用了大量的延迟操作但在Kafka中 并没用使用JDK自带的Timer或是DelayQueue用于延迟操作,而是使用自己开发的DelayedOperationPurgatory组件用于管 ...
- .Net之时间轮算法(终极版)定时任务
TimeWheelDemo 一个基于时间轮原理的定时器 对时间轮的理解 其实我是有一篇文章(.Net 之时间轮算法(终极版))针对时间轮的理论理解的,但是,我想,为啥我看完时间轮原理后,会采用这样的方 ...
- Kafka解惑之时间轮 (TimingWheel)
Kafka中存在大量的延迟操作,比如延迟生产.延迟拉取以及延迟删除等.Kafka并没有使用JDK自带的Timer或者DelayQueue来实现延迟的功能,而是基于时间轮自定义了一个用于实现延迟功能的定 ...
- 时间轮算法在Netty和Kafka中的应用,为什么不用Timer、延时线程池?
大家好,我是yes. 最近看 Kafka 看到了时间轮算法,记得以前看 Netty 也看到过这玩意,没太过关注.今天就来看看时间轮到底是什么东西. 为什么要用时间轮算法来实现延迟操作? 延时操作 Ja ...
- 时间轮TimeWheel工作原理解析
时间轮工作原理解析 一.时间轮介绍 1.时间轮的简单介绍 时间轮(TimeWheel)作为一种高效率的计时器实现方案,在1987年发表的论文Hashed and Hierarchical Timing ...
- SpringBoot定时任务 - 经典定时任务设计:时间轮(Timing Wheel)案例和原理
Timer和ScheduledExecutorService是JDK内置的定时任务方案,而业内还有一个经典的定时任务的设计叫时间轮(Timing Wheel), Netty内部基于时间轮实现了一个Ha ...
随机推荐
- 一些对dp突然的理解
突然想到了一些理解,感觉有些模糊,怕忘记,就赶紧记下来就是对于状态的设计 用01背包举例子吧,我们设计状态的时候一定是要保证所有可能在最后优秀的子状态在前面的时候是能够保留下来的也就是我们的状态设计要 ...
- 牛逼!Github上最有价值的一个开源项目!
哈喽,我是老鱼,一名致力于在技术道路上的终身学习者.实践者.分享者! 今天介绍的这个项目,我愿称之为Github最有价值的开源项目! 一个小而全而美的第三方登录开源组件,相信你一定能用的上~ Just ...
- sql删除进程
使用一下语句杀掉进程 USE master go DECLARE @dbname VARCHAR(200) SET @dbname = 'xxxx' --要关闭进程的数据库名 DECLARE @sql ...
- Qt 迭代器
目录 (一) java风格迭代器 1. QListIterator类 1. 初始化 2. findNext() 3. findPrevious() 4. hasNext() 5. hasPreviou ...
- mybatis 操作 mysql 大批量插入,数据分页处理
/** * 大批量插入,数据分页处理 * * @param tableName 临时表名称 * @param mapHead 临时表属性 Map,key = 临时表字段属性, value = 具体值. ...
- 用ps命令查看进程的内存
http://blog.csdn.net/tigerscorpio/article/details/5960705 http://blog.csdn.net/licanhua/article/deta ...
- L2-029 特立独行的幸福
#include <bits/stdc++.h> using namespace std; bool isyifu[10010]; bool isunhappy[10010]; bool ...
- 你所不知道的ASP.NET Core进阶系列(三)
前言 一年多没更新博客,上一次写此系列还是四年前,虽迟但到,没有承诺,主打随性,所以不存在断更,催更,哈哈,上一篇我们细究从请求到绑定详细原理,本篇则是探讨模型绑定细节,当一个问题产生到最终解决时,回 ...
- 超详细的Mysql锁 实战分析,你想知道的都在这里~
1.mysql回表查询 在这里提起主要是用于说明mysql数据和索引的结构,有助于理解后续加锁过程中的一些问题. mysql索引结构和表数据结构是相互独立的,根据索引查询,只能找到索引列和主键聚簇索引 ...
- CompletableFuture进阶
CompletableFuture进阶 1.异步任务的交互 异步任务交互指将异步任务获取结果的速度相比较,按一定的规则( 先到先用 )进行下一步处理. 1.1 applyToEither applyT ...