在系统中增加quartz定时任务集群?
做过类似的功能,不一定非得用分布式定时任务,还是要结合项目实际来选择具体的解决方案;从简单的说起,给大家介绍几个(不一定要选高大上的方案,适合最重要)。
比如数据库中每天都会有一百万条数据待处理,一个定时任务(记为A)要处理完这一百万条数据,需要10个小时;如果想加快这个处理速度,我们首先能想到的是多部署一个批处理程序(记为B),这时候理论上需要10/2=5个小时,可以把任务都处理完。
方案一:待处理任务表增加一个处理标志的字段,例如0=待处理,1=处理中,2=处理完成;当A任务取到待处理数据的时候,将此字段更新成1,处理完之后更新成2;当字段=1/2的时候,B任务不会取到这条数据;但是这种方法的问题极大,因为很容易发生一条待处理任务在被A查询到,但是未更新处理状态前,就被B任务取到,这样就会造成重复处理的问题。
方案二:把处理任务进行人为的划分,A处理一批数据,B处理一批数据。可以从纯数据角度划分,比如id%2=0的A处理,id%2=1的B处理,也可以从业务角度划分,比如某个字段in(A,B,C)的A处理,某个字段in(X,Y,Z)的A处理;这样做不会造成数据重复处理,但是也有一些问题:
数据不一定能够平均分配,比如字段in(A,B,C)的数据有90万条,字段in(X,Y,Z)的有10万条。
难以扩展,因为条件是写死的,所以如果要增加减少机器的话比较麻烦;
如果其中一台机器挂掉,那么这部分数据就不会处理。
方案三:方案一改进一下,增加分布式锁(可以是数据库、Redis、ZK),谁能抢到锁,谁才能提取待处理任务,并更新处理状态,比如一次提取一万行数据,并把这些数据的待处理状态更新成【处理中】,然后把锁释放掉,再由其他的节点抢锁。这种方案需要考虑的东西也不少:
要考虑锁超期的问题:如果A抢到锁,还没释放锁之前A就挂掉了,那么所有任务都会被卡主。
如果锁超期被释放掉,A处理到一半的任务还需要被其他任务处理(失效转移)。
可以和方案二结合,做任务分片,批处理程序抢到锁后,领取一个任务分片进行处理。
方案四:直接采用分布式任务处理框架,我熟知的就是Elastic-Job了,它的功能更为强大,不过主要的功能嘛,你能理解前三个方案的话,这个方案也就容易理解了(基本上就是上面那些东西)。
我将持续分享Java开发、架构设计、程序员职业发展等方面的见解,希望能得到你的关注。