HangFire循环作业中作业因执行时间太长未完成新作业开启导致重复数据的问题...

背景

HangFire有个很奇怪的现象,就是即使你设置的循环作业是一天一次,但是每次作业执行很长时间,我们假设是1小时,那么差不多在开始执行之后的30分钟之后,如果还在执行job,系统就会自动帮你重新开启了新的job执行。也就是撇开循环周期的影响,我一个长时间的作业,超过三十分钟的,那么系统又会在你还在执行的时候,三十分钟之后又起一个来帮你执行。

问题窥探

我之前做项目的时候,就遇到这个问题,莫名其妙。开始的时候,我还以为可以像Quartz加个[DisallowConcurrentExecution]了事。

后面找到这个

706eee227b22ecf7e1b28166c8d54308.png

但是测试了下,不起作用啊。而且一旦启用分布式部署,这个就算有用,到时候不也没用了,后面想想直接来个干脆的,分布式锁。

解决办法

1、进入job的时候,定义一个key,判断是否正在执行。

string uniqueKey = string.Empty;
            string key = "xxxxx";
            if (!CacheExtension.getInstance().AddUnique($"{key}_unique", 1, DateTimeOffset.Now.AddDays(365)))
            {
                LogExtention.getInstance().WriteCustomLogAsync("", "", true, "上批次还未执行结束--xxxxxxjob");
                return;
            }
            uniqueKey = $"{key}_unique";

2、redis-StringSet保证key是唯一的。

/// <summary>
        /// 新增,若缓存中已存在相同KEY,则返回false,判断高并发时使用
        /// </summary>
        public bool AddUnique(string key, object o, DateTimeOffset expiration, string dependsOnKey = null)
        {
            key = AddSysCustomKey(key);
            var ts = expiration - DateTimeOffset.Now;
            return _client.StringSet(key, ConvertJson(o), ts, When.NotExists);
        }

3、执行完成的时候,去掉锁。

try
            {
            //todo            
            }
            finally
                        { 
‍                ‍
                    CacheExtension.getInstance().Remove(uniqueKey);


            }

总结

1、这样的话,就能在旧的还未完成之前,新的进来,直接return,保证唯一性,也支持了分布式处理。

2、分布式锁在很多场景,还是很实用的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值