在实际业务场景中,经常会有批量处理任务的需求,批量数据一般都是通过job跑批任务来完成的。
在跑批任务处理数据的时候有两种情况会导致数据被重复处理。
一、跑批任务中的方法运行超时,dubbo接口默认会再次调用一次。
一个跑批往往是一个或多个完整的事务,完全处理完成才会提交事务。当消费端向服务端发出一次请求,服务端处理超时时(实际处理并没有停止还在进行中),服务端会再次发出一次请求,此时消费端会再次执行方法,由于上一个正在进行的事务还未完全处理完,数据还未提交,所以查寻到的数据很可能是上一个事务正在处理的数据。当上一个方法执行完成,事务也提交了,第二次调用的方法也执行完成,提交事务时就有可能会发生冲突:主键冲突、重复处理。
解决方法:调整消费端超时时间,根据实际情况适当延长,设置尝试次数为0,调用超时,不再重复调用。
<dubbo:reference interface="ServiceClass" id="serviceName"> <dubbo:method name="methodName" timeout="20000" retries="0"/> </dubbo:reference>
二、跑批任务频率过高,当某一次跑批拿到数据量过大,运行时间超出任务的频率。
假若正常情况下,一个跑批任务执行时间为30s,频率设置为2min执行一次,超时时间为1min。突然有一次导入了一大批数据,任务执行时间远大于2min,当任务执行到1min时,系统默认判定方法执行超时,任务结束,到2min时再次调用此方法,此时上一个跑批任务的方法实际上还未执行结束,这样就导致方法重复调用,任务重复处理。
解决方法,给要处理的数据加一个状态,执行任务时,查询”待处理“的数据,查询出来的数据修改状态为”处理中“,处理完毕后次改状态为”处理完成“,这样即使方法被重复调用,任务重复执行,也不会导致数据被重复处理。