概述
在理解kafka的时间轮定时器的概念的时候,我们需要提前了解下java里面的DelayQueue的概念,因为在kafka的时间轮定时器其实是基于DelayQueue来实现的。
最后我希望一定要好好看博文末尾的参考文献,将这篇博文+参考文献就可以把时间轮理解的很清楚。
定时器选型
传统方案
对于实现一个定时任务,一般的做法是将定时任务写入数据库,通过一个线程定时查询出将要到期的任务,再执行任务相关逻辑。该方案的优点是实现简单,尤其适合单机或者业务量比较小的场景来。但是缺点也很明显:在分布式且业务量较大的场景中会引入很多复杂性。首先,需要设计一套合理的分库分表逻辑,以及集群任务负载逻辑。其次,即使做到这些,也会由于某些场景定时任务时间集中在某个时间点,导致集群单节点压力过大。再次,需要合理的预估容量,否则后续线性存储扩容将会非常复杂。
我们的物流处罚其实就是采用类似的机制去实现扫描的,但是后来因为分库等原因最后还是借用了rocketMq来实现的,与其说借用了rocketMq还不如说借用了rocketMq内部的定时器的实现,在开源的4.x的rocketMq版本中其实本质上还是用定时任务加队列的方式来发现任务是否过期。
传统的方法一个弊端就在于一般情况下我们按照过期粒度,譬如1分钟、10分钟、1小时、24时小时等粒度组装Timer+队列,然后同时有n个线程扫描各自的队列,然后发现其中过期的进行处理,在大量扫描过程中其实很多任务可能还是没有过期的,也就是说白白进行了扫描。那么时间轮在这方面是不是有了优化呢。
时间轮方案
时间轮方案将现实生活中的时钟概念引入到软件设计中,主要思路是定义一个时钟周期(比如时钟的12小时)和步长(比如时钟的一秒走一次),当指针每走一步的时候,会获取当前时钟刻度上挂载的任务并执行,整体结构如图1。
kafka-timer结构
说明
kafka的内部Timer其实是自己实现的一个定时器(其实就是一个时间轮),对外提供两个接口,一个接口是由外部调用添加任务add(TimerTask),一个接口是由外部驱动时间轮轮转(advanceClock),当发现任务过期以后则提交专门的任务线程去执行。时间轮内部的真正细节是下面这个图。
kafka时间轮
说明:
1、kafka时间轮的核心组成部分包括tickMs(时间格代表时间)、wheelSize(时间轮格子的数量)、startMs(时间轮开始时间)、taskCounter(任务个数)、delayQueue(延迟队列)。
2、我们每次通过从delayQueue中获取过期任务,如果能够获取到过期任务说明时间轮往前进一格。
父时间轮
说明:
1、其实父时间轮本质上其时间格代表的时间是子时间轮一周代表的时间而已。
TimerTaskList对象
说明:
其实TimerTaskList对象就是一个双向列表而已。
时间格移动概念
参考文献
文章知识点与官方知识档案匹配,可进一步学习相关知识云原生入门技能树首页概览8581 人正在系统学习中 相关资源:滚齿机速查挂轮软件2.1版本.zip_插齿机挂轮计算软件-制造文档类…
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!