go-zero 如何应对海量定时/延迟任务?

本文详细介绍了go-zero中的timingWheel机制,用于高效管理大量定时和延迟任务。通过时间轮的设计,降低了任务维护成本,仅在执行时轮询任务,避免了优先队列的操作开销。文章探讨了初始化、任务操作和执行流程,强调了timeWheel如何推进时间并执行任务,以及在时间精度和扩展性方面的考量。
摘要由CSDN通过智能技术生成

一个系统中存在着大量的调度任务,同时调度任务存在时间的滞后性,而大量的调度任务如果每一个都使用自己的调度器来管理任务的生命周期的话,浪费cpu的资源而且很低效。

本文来介绍 go-zero延迟操作,它可能让开发者调度多个任务时,只需关注具体的业务执行函数和执行时间「立即或者延迟」。而 延迟操作,通常可以采用两个方案:

  1. Timer:定时器维护一个优先队列,到时间点执行,然后把需要执行的 task 存储在 map 中
  2. collection 中的 timingWheel ,维护一个存放任务组的数组,每一个槽都维护一个存储task的双向链表。开始执行时,计时器每隔指定时间执行一个槽里面的tasks。

方案2把维护task从 优先队列 O(nlog(n)) 降到 双向链表 O(1),而执行task也只要轮询一个时间点的tasks O(N),不需要像优先队列,放入和删除元素 O(nlog(n))

我们先看看 go-zero 中自己对 timingWheel 的使用 :

cache 中的 timingWheel

首先我们先来在 collectioncache 中关于 timingWheel 的使用:

timingWheel, err := NewTimingWheel(time.Second, slots, func(k, v interface{}) {
  key, ok := k.(string)
  if !ok {
    return
  }
  cache.Del(key)
})
if err != nil {
  return nil, err
}

cache.timingWheel = timingWheel

这是 cache 初始化中也同时初始化 timingWheel 做key的过期处理,参数依次代表:

  • interval:时间划分刻度
  • numSlots:时间槽
  • execute:时间点执行函数

cache 中执行函数则是 删除过期key,而这个过期则由 timingWheel 来控制推进时间。

接下来,就通过 cachetimingWheel 的使用来认识。

初始化

// 真正做初始化
func newTimingWheelWithClock(interval time.Duration, numSlots int, execute Execute, ticker timex.Ticker) (
    *TimingWheel, error) {
    tw := &TimingWheel{
        interval:      interval,                     // 单个时间格时间间隔
        ticker:        ticker,                       // 定时器,做时间推动,以interval为单位推进
        slots:         make([]*list.List, numSlots), // 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值