多个工人同时触发了重复工作

时间:2018-02-03 06:54:48

标签: c# concurrency hangfire

我正在使用最新的稳定篝火(1.6.17.0)。

我有4-6名工人在任何时候并行运行。

当新员工启动时,他们正在验证是否已创建好所有作业 - 并使用以下代码添加/更新应运行的所有作业:

var jobId = HangfireConsts.FormatReccurringJobStore(storeId); 

RecurringJob.AddOrUpdate(
    jobId,
    () => ExecuteRefreshStore(storeId),
    Cron.HourInterval(8),
    null,
    HangfireConsts.QueueStores);

我认为这应该是无害的,因为我使用的是AddOrUpdate() - 所以最糟糕的情况是它应该只更新现有的。锁定系统将确保每个作业都添加一次(基于jobId)。这使得我甚至可以为调度程序启动一个全新的干净模式,并获得持久的结果 - 因为所有重复的作业都将被重新创建。

然而,我可以看到一些工作开始,完全相同的jobId,在多个工人的同一时间被触发。有时在2名工人上并行,有时在3名工人上并行,有时在4或5名(6名)。

怎么可能?这是一个错误吗?

工人1 Worker 1

工人2 Worker 2

工人3 Worker 3

2 个答案:

答案 0 :(得分:1)

以下内容基于Performing recurrent tasks文档的评论:

  • 一种方法是不创建预定作业,而是创建单次延迟作业,在完成处理时创建新的延迟作业。

    这个问题的主要问题是,如果你启动两个处理器,你现在必须决定他们中的哪一个安排第一份工作。

  • 另一种方法是在作业方法上使用[DisableConcurrentExecution]属性和0超时以及AutomaticRetry来避免重试(并警告日志):

    [DisableConcurrentExecution(0)]
    [AutomaticRetry(Attempts = 0, LogEvents = false, OnAttemptsExceeded = AttemptsExceededAction.Delete)]
    

答案 1 :(得分:0)

嘿,我们遇到了同样的问题,发现有人对我们的Cron表达式进行了更改,试图添加次分钟的问题,这对我们造成了上述问题。

坏:

 public static CronExpression Minutely()
        {
            return new CronExpression("* * * * * *");
        }

    public static CronExpression Hourly(int minute)
        {
            return new CronExpression($"* {minute} * * * *");
        }

好:

 public static CronExpression Minutely()
        {
            return new CronExpression("* * * * *");
        }

 public static CronExpression Hourly(int minute)
        {
            return new CronExpression($"{minute} * * * *");
        }