ecodeclub / ecron

大规模分布式任务调度系统(学习版)
Apache License 2.0
63 stars 21 forks source link

基于MySQL 的抢占式存储引擎实现 任务2:抢占优化 #11

Closed flycash closed 1 year ago

flycash commented 1 year ago

前置条件:#10 已经完成

在 #10 任务1 的基础上,你需要做这个改进: 对于续约来说,你启用一个延时队列,可以使用 ekit 里面的延时队列,即维持一个 goroutine 每次都从队列里面获取一个已经被抢占的任务,在获取到之后就要开始续约。

注意,它和 #10 的区别就是用一个延时队列 + 一个 goroutine 取代了原本一个任务一个 goroutine 的模型,达到了优化性能的效果。

但是在启用了延时队列之后就会有一个问题:一个 Goroutine 可能根本来不及续约。比如说一个任务已经到了可以续约的时间,但是因为数据库性能之类的问题,导致一直没有把它取出来续约。

有两种可行的优化方案:

总体上来说,我认为在当下我们的数据库没有考虑采用分库分表功能的时候,批量更新还是蛮不错的。和负载均衡的冲突,我们可以后面继续讨论,至少负载均衡怎么做,我还没一个非常优秀毫无破绽的设计。

hookokoko commented 1 year ago

@flycash 不太确定我这种下面说的情况对你说的批量更新理解的是不是正确

我理解的这种批量更新的方案会有续约延迟的问题。 因为我从延迟队列中取任务时,不可能在同一时刻出队,所以这里出队的时候需要设置一个等待时间范围,比如拿到5s内需要续约任务,那么续约的误差最多可能有5s。

flycash commented 1 year ago

@flycash 不太确定我这种下面说的情况对你说的批量更新理解的是不是正确

我理解的这种批量更新的方案会有续约延迟的问题。 因为我从延迟队列中取任务时,不可能在同一时刻出队,所以这里出队的时候需要设置一个等待时间范围,比如拿到5s内需要续约任务,那么续约的误差最多可能有5s。

这里我们采用一种比较宽松的策略,就是续约不需要非常精确。比如说一分钟续约一次,那么连续两次或者三次续约失败才算是没续约。因此你其实有很多时间;

或者照你说的,秒级别的差距是可以理解的。我们最开始在考虑这个任务调度的时候,对于时间的保证就不要很精确,因为太难了。