前言
在上一篇文章中我们讲解了空闲检测机制的由来, Netty
对应的心跳实现以及源码查看, 本次主要讲解什么是时间轮
这是我的Netty
专栏 欢迎大家关注
时间轮
时间轮是一种实现延迟功能的算法, 它在Linux
内核中使用广泛, 是Linux
内核定时器的实现方法和基础之一.
时间轮是一种高效来利用线程资源来进行批量化调度的一种调度模型, 把大量的调度任务全部绑定到同一个调度器上, 利用这个调度器来进行所有任务的管理, 触发以及运行.
单层时间轮
图片来源于网络
时间轮的创意来自于生活中的时钟, 在时间轮机制中有时间槽和时间轮的概念, 对应的分别是时钟的刻度和时针跳动的一个周期, 当有新任务产生的时候, 会将任务放置到对应的时间槽内, 每过一个时间周期就会执行下一个时间槽内的任务
图片来源于网络
多层时间轮
但是在上述时间轮也有一些缺点, 假设每个时间周期是 1s, 时间轮共有六十个节点, 那么当我设置一个任务为 70s 之后执行的话会在 10s(70 % 60) 后执行, 这显然不符合我们的预期
所以在时间爱轮中还有一个参数 round, 用来记录几圈之后执行
当我们解决了时间轮圈数问题之后就会发现, 只有当一个任务的 round 为 0 才会执行该任务, 那么就会造成时间轮的空转问题, 还是上面刻度为 60 的时间轮, 假设一个任务在 600s 后执行, 则该任务的执行刻度为 0s, round 为 10, 时间轮空转 10 圈才会执行该任务, 造成了大量资源的浪费, 于是多层时间轮
应运而生
图片来源于网络
如图所示, 第一层时间跨度为 1ms, 第二层时间跨度为 20ms, 第三层时间跨度为 400ms, 当任务为 501ms 执行的时候, 会先记录在 刻度为 1(501/4) 的地方, 当执行到 1 时, 余下的 401(501-400) 会进入第二层的 5(501/20) 刻度, 同时 round == 1, 代表一圈后的 5刻度, 执行完第二层之后, 还余 1 会进入第三层的 1 刻度, 至此才算是结束
使用场景
kafka , Netty, Zookeeper 等高并发的一般都有时间轮的实现
以Netty
系统为例, 在其中是会存在大量连接的, 在每个连接中都存在相应的事件任务, 而大量的事件任务如果每一个任务都启动一个timer
调度器来管理任务的生命周期的话, 会造成CPU的资源浪费且低效, 于是HashedWheelTimer
应运而生, HashedWheelTimer
就是以时间轮为基础进行设计的