大数据开发:Kafka延迟队列

2021-06-03 18:08:42 浏览数 (1)

Kafka作为实时消息队列的一个重要框架,在大数据技术架构搭建层面,越来越得到重用。相应的,Kafka在大数据技术生态当中的地位,也越来越重要。今天的大数据开发学习分享,我们就来讲讲Kafka延迟队列的部分。

kafka基于时间轮(TimingWheel)自定义了一个用于实现延迟功能的定时器。

时间轮是一个存储定时任务的环形队列,底层采用数组实现,数组中的每个元素可以存放一个定时任务列表(TimerTaskList)。TimerTaskList是一个环形的双向链表,链表中的每一项表示的都是定时任务项(TimerTaskEntry),其中封装了真正的定时任务TimerTask。

时间轮由多个时间格组成,可以想象成时钟。

tickMs:每个时间格代表当前时间轮的基本时间跨度

wheelSize:时间轮的时间格个数是固定的,可用wheelSize来表示

所以整体时间轮的时间跨度interval=tickMs*wheelSize

currentTime:时间轮还有一个表盘指针,用来表示时间轮当前所处的时间,currentTime是tickMs的整数倍。

举个栗子:

tickMs=1ms,wheelSize=20,那么interval=1*20=20ms

初始情况下currentTime指向0时间格。此时一个定时为2ms的任务插入进来会存放到时间格为2的TimerTaskList中。

随着currentTime指针随着时间不断推进,当currentTime指向2时间格时,就需要将时间格2所对应的TimeTaskList中的任务做相应的到期操作。

此时若又有一个定时为8ms的任务插入进来,则会存放到时间格10中,currentTime再过8ms后会指向时间格10。

同时一个19ms的任务插入进来,会存放到时间格1中。

如果有一个定时任务的时间大于interval怎么办?

直接扩充wheelSize的大小?这个是没底线的,定时任务时间不知道会有多大。而且如果wheelSize很大,不仅占用很大的内存空间,而且效率也会拉低。

Kafka为此引入了层级时间轮的概念,当任务的到期时间超过了当前时间轮所表示的时间范围时,就会尝试添加到上层时间轮中。

第一层的时间轮interval=20ms,那么第二层的时间轮的tickMs=20ms。每一层的wheelSize是相同的额,所以第二层的时间跨度interval=20*20=400ms。同理,第三层时间轮的interval=400*20=8000ms。

如果有一个350ms的定时任务,第一层时间轮无法满足,就升级到第二层时间轮中,最终被插入到第二层时间轮中时间格17所对应的TimerTaskList中。其他层级同理,如一个450ms的定时任务会放在第三层的第一格中。

以450ms的定时任务为例,当第三层的currentTime指向时间格1时,此时450ms的定时任务还剩下50ms,会有一个时间轮降级操作。此时第一层时间轮的总体时间跨度不够,而第二层足够,所以该任务被放到第二层时间轮到期时间为[40ms,60ms)的时间格中。再经历40ms后,任务还剩下10ms,会再次降级放到到第一层时间轮[10ms,11ms)的时间格中。之后再经历10ms,此任务真正到期,最终执行相应的到期操作。

总的来说,延迟队列是Kafka当中的一个重要功能点,对于大数据背景下的实时消息队列的处理,有重要的作用。

0 人点赞