首页 > 解决方案 > 每次定时器完成时运行函数的最有效方法,但有大量定时器(千/百万)

问题描述

我正在运行一项服务,用户上传一个持续时间,并且每次计时器用完时都必须重复执行一个函数。

例如,用户说“每 5 分钟运行一次”,然后此函数必须每 5 分钟运行一次。这是通过 API 完成的。

对于少数计时器,这是微不足道的:

func doEvery(d time.Duration, f func(time.Time)) {
    for x := range time.Tick(d) {
        f(x) // Run the function every d duration
    }
}

我可以在 goroutine 中运行每个计时器,而且效果很好。WaitGroups我可以使用一些基本和同步功能来启动和停止一切。

但是,如果我有数千或数百万个计时器怎么办?我可以为每一个创建一个 goroutine,但感觉效率很低。这不是二郎。

我应该有多个工作队列,按“延迟”排序,并简单地为更频繁的功能分配更多的工作人员吗?如果计时器未准备好,则将其放回队列中。

这也不理想,因为工作人员忙于等待(弹出,检查时间,推入队列)而不是阻塞直到下一个计时器完成。

也许我可以有某种地图,由剩余的持续时间索引?我不确定这里最好的方法是什么。

标签: gotimerscale

解决方案


我最近构建了这种解决方案,用户可以根据他们的间隔设置获得通知。我使用 rabbitMQ 和两个 go 脚本制作了一个工作池模型。一个 go 脚本使用下面的 cron 模块在消息队列中创建作业

https://github.com/robfig/cron

另一个 go 脚本是使用消息队列并采取行动的工作脚本。为了扩展,我正在运行多个工作脚本实例。工作脚本的自动缩放可以通过rabbitMQ中的消息数来完成


推荐阅读