源码分析ElasticJob任务错过机制与幂等性

任务在调度执行中,由于某种原因未执行完毕,下一次调度任务触发后,在同一个Job实例中,会出现两个线程处理同一个分片上的数据,这样就会造成两个线程可能处理相同的数据,因此Elastic-Job引入幂等机制来解决上述问题。再重申一次ElastciJob的分布式是数据的分布式,一个任务在多个Job实例上运行,每个Job实例处理该Job的部分数据(数据分片)。

本文重点分析ElasticJob是如何做到如下两点的。

ElasticJob如何确保在同一个Job实例中多个线程不会处理相同的数据

ElasticJob如何确保数据不会被多个Job实例处理

为了解决上述这种情况,ElasticJob引入任务错过补偿执行(misfire)与幂等机制。

ElasticJob幂等原理

场景:例如任务调度周期为每5s执行一次,正常每次调度任务处理需要耗时2s,如果在某一段时间由于数据库压力变大,导致原本只需要2s就能处理完成的任务,现在需要16s才能运行,在一批数据处理未完成的情况下,每5s又会触发一次调度,如果不加以控制的话,在同一个实例上根据分片条件去查询数据库,查询到的数据有可能相同(部分相同),这样同一条任务数据将被多次处理,如果业务方法未实现幂等,则会引发非常严重的问题,那ElasticJob是否可以避免这个问题呢?

答案是肯定。elasticJob提供了一个配置参数:monitorExecution=true,开启幂等性。

一个任务触发后,将执行任务处理逻辑,其入口:

代码@1:在一个调度任务触发后如果上一次任务还未执行,则需要设置该分片状态为mirefire,表示错失了一次任务执行。

代码@2:如果该分片被设置为mirefire并开启了事件跟踪,将事件跟踪保存在数据库中。

接下来详细分析JobFacade.misfireIfRu-nning的实现逻辑:

如果存在未完成的分片,则调用setMis-fire(items)方法,在开启monitorExecut-ion(true)的情况下,在分片任务开始时会创建/jobname/sharding//running节点,在任务结束后会删除该目录,所以在判断是否有分片正在运行时,只需判断是否存在上述节点即可。如果存在,调用setMisfire方法。

PS:ElasticJob只有在monitorExecuti-on=true的情况下,才会创建/jobname/sharding//running,m-isfire机制才能生效。

其实现方式为分配给该实例下的所有分片创建持久节点/jobname/shading//misfire节点,注意,只要分配给该实例的任何一分片未执行完毕,则在该实例下的所有分片都增加m-isfire节点,然后忽略本次任务触发,等待任务结束后再执行。

在任务执行完成后检查是否存在/jobname/sharding//misfire节点,如果存在,则首先清除misfie相关的文件,然后执行任务。

幂等实现方案总结:

在下一个调度周期到达之后,只要发现这个分片的任何一个分片正在执行,则为该实例分片的所有分片都设置为mis-fire,等任务执行完毕后,再统一执行下一次任务调度。

ElasticJob数据分片

ElasticJob基于数据分片,不同分片根据分片参数(人为配置),从数据库中查询各自数据(任务数据分片),如果当节点宕机,数据会重新分片,如果任务未执行完成,然后执行分片动作,数据是否会被不同的任务同时处理呢?

答案是不会,因为当节点宕机后是否需要重新分片事件监听器会监听到Job实例代表的节点删除,设置重新分片,在任务被调度执行具体处理逻辑之前,需要重新分片,重新分片的前提又是要所有的分片的任务全部执行完毕,这也依赖是否开启幂等控制(monitorExecution)。

如果开启,ElasticJob能感知正在执行处理的分片,重新分片需要等待当前所有任务全部运行完毕后才会触发,故不会存在不同节点处理相同数据的问题。

问答:

1、如果一个任务JOB的调度频率为每10s一次,在某个时间,该job执行耗时用了33s(平时只需执行5s),按照正常调度,应该后续会触发3次调度,那该job后执行完,会连续执行3次调度吗?

答案:在33s这次任务执行完成后,如果后面的任务执行在10s内执行完毕的话,只会触发一次,不会补偿3次,因为Ela-sticJob记录任务错失执行,只是创建了misfire节点,并不会记录错失的次数。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181211G0HMPH00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 yunjia_community@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券