定时任务的解决方案

RPC中很多场景都会用到定时任务,比如调用端请求超时的处理逻辑,我们当时使用的是Future去实现调用,如下

调用端在向服务器发送之前会创建一个Future,然后记录下这个Future创建时间和这个Future的超时时间,并有一个定时任务进行检测,当Future到达超时时间没有被处理时,执行超时逻辑。

sleep

每创建一个Future,就启动一个线程,之后sleep,到达超时时间就触发请求超时的处理逻辑。
弊端是:高并发场景下,请求超时时间5s的话,单机每秒一万请求的话,将会有10万的线程。

轮询

用一个线程来处理所有定时任务,每隔一段时间扫描一下所有的超时任务,当发现有超时的,即执行超时任务。比如调用端刚好在1s内发送了1万次请求,5s后超时,扫描的线程会不停的扫描遍历,总共扫描50次1万个任务,本来只需要最后1s扫描即可,但是从头开始扫的话额外扫描了40次。

高并发下轮询同样是一种很耗资源的操作,会带来很大的CPU损耗

时钟轮

时钟轮是一种可以减少额外扫描操作的一种技术。

时钟轮的实现原理和生活中的时钟跳动的原理很相似,有两个概念

  • 时间槽:相当于时钟的刻度
  • 时钟轮:秒针与分针转动的一个周期

将任务放到时间槽中,每隔固定的时间,就会从一个槽位跳到另外一个槽位,相当于秒针转动

时钟轮分多层,下一层时钟轮的每个槽位时间是当前时间轮整个周期的时间。

当时钟轮将一个周期的所有槽位都跳动完之后,就会从下一层时钟轮中取出一个槽位的任务,重新分配到当前的时钟轮中。

举例解释:
假设时钟轮有10个槽位,每一轮的周期是1s,每个槽位的单位时间就是100ms,下一层的时间轮周期为10s,每个槽位时间为1s。

两个时钟轮如下:
时钟轮在RPC中的应用
假设有3个任务,任务A 90ms后执行,任务B 610ms执行,任务C 1秒610ms执行,放入槽位,任务A在当前时钟轮第0槽位,任务B在当前时钟轮第6槽位,任务C在下一时钟轮第1号槽位。如下:
时钟轮在RPC中的应用
当前时钟轮走一轮之后,任务A和任务B都执行完毕,在下一层时钟轮中取出任务C,放入当前时钟轮,则放在第6槽位,继续执行当前时钟轮。

时钟轮在RPC中的应用
时间轮解决了过多的重复扫描问题,解决了CPU浪费的问题。

RPC中时钟轮的应用

  • 调用端的请求超时处理
  • 调用端和服务端的启动超时
  • 定时心跳机制,执行完之后时间重置,继续执行

注意

  • 时间槽位的单位时间越短,时间轮触发任务的时间就越精确
  • 时间轮的槽位越多,那么一个任务被重复扫描的概率就越小,因为只有在多层时钟轮中 的任务才会被重复扫描。

相关文章:

  • 2021-07-01
  • 2021-04-06
  • 2021-07-15
  • 2022-12-23
  • 2021-09-07
  • 2021-12-30
  • 2021-09-06
  • 2021-07-31
猜你喜欢
  • 2021-12-10
  • 2022-12-23
  • 2021-12-14
  • 2021-05-12
  • 2022-12-23
  • 2021-08-15
  • 2021-12-24
相关资源
相似解决方案