1.ElasticJob的意义
设想,现在有一批量很大的数据,要对这些数据进行逐条推送,普通的思路是同步将这些数据逐条推送,从第一条推送到第n条;进阶思路,起若干个线程,每个线程分别执行一部分数据的推送,比如有10个线程,则每个线程执行十分之一数据的推送;
进阶思路的优点:异步并行,提高推送效率;
进阶思路的缺点:如何对数据进行分块;异步线程中如果有一个或多个失效怎么办,这部分失效线程的推送任务如何保证正确推送;
ElasticJob的实际就是基于上述进阶思路的一种保全措施;同样的,使用异步并行推送,并提出了任务分片机制和失效转移机制;
2.elasticjob的节点注册:
使用基于ZK的节点机制,每个实例在启动的时候,会调用elasticjob框架内的注册方法去zk上注册一个节点;这与大部分中间件将zk作为路由管理工具相似;
在代码中,需要对elasticjob的作业进行配置;elasticjob独享一份关于zk的配置,包括zk的地址和命名空间,命名空间就是当前作业的名字;一个作业独享一个命名空间,当实例需要使用elasticjob时,需要制定这个实例进行什么作业以及注册管理zk在哪个地址;所有进行同一个作业的实例均会在启动时,在对应作业节点下建立子节点:
-作业名
-服务1
-服务2
-服务3
实例建立的节点为改实例中具体进行作业的类名;
实例节点结构:
-实例1
-config
-instance
-sharding
-servers
-leader
config节点存储的是配置文件的信息,以json串存储,包括当前作业的分片数,是否开启失效转移;
instance节点存储的是实例的信息,包括实例的ip和id;一个服务下可以有多个实例,比如同一个SERVICEA,我起3个实例,则instance下会有三个节点:
-instance
-ip1@id1
-ip2@id2
-ip3@id3
instance节点下的子节点均为临时节点,当实例消失时消失,实例上线时注册;
sharding节点存储的是作业的分片信息,分片信息下有对应分片数个子节点:
-sharding
-分片0
-分片1
-分片2
在子节点下有节点instance,这个节点表示当前运行这个作业分片的服务:
-分片0
-instance(ip1@id1)
服务通过抢锁来获取分片号,然后根据分片号来筛选作业进行操作;
若当前分片正在被执行,则会有running节点;
servers节点存储的是执行作业的服务所处的服务器ip
leader节点用户存储主节点的信息,包含election,sharding和failover三个子节点;
election节点用于选主,包含子节点instance和latch(主节点ip@id,锁),
sharding节点用于分片;
failover节点用于失效转移,失效转移可在配置中配置是否开启,若未开启失效转移,则该节点不会注册;
3.elasticJob的选主机制和分片机制:
首先,elasticJob的主从关系,在执行作业上来讲,是完全没有区别的,主从节点唯一的区别在于,主节点需要对作业进行分片;
分片动作:
原生elasticJob除了支持配置定义分片数以外,还支持通过对zk的写来更改config内的内容以达到更改分片数的目的;
主节点需要根据当前分片节点的内容来定义分片节点,其实现是通过监听zk特定目录,当分片数发生变化,作业不在被执行时对sharding节点下的分片节点进行一个实例的分配;
实现步骤:
1.获取可用实例节点;
2.如果正在选主,则阻塞至选主结束;
3.如果sharding节点下有runnig节点(正在执行作业),则等待作业结束;
4.重置分片节点下的proccessing节点,这个节点标识正在进行分片;
5.清除分片节点下的instance节点,这个节点标识这个分片被分配到哪个实例执行;
6.根据实例id和分片id按算法进行匹配;
7.删除分片节点下多余的实例节点(一个作业分片只能被分配到一个执行实例);
选主机制:
所有实例在启动时在zk上注册自己节点并监听leader节点;
所有实例依次获取latch锁并建立排序节点,并监听上一个节点的节点删除时间,这一过程是阻塞的(比如实例A的排序节点为2,实例B的排序节点为1,则A监听B的节点直到发生节点删除事件);
若排序节点是最小,则判断leader节点下instance节点是否存在;
若存在则说明已有未失效的主节点,删除latch下的排序节点,放弃该次选举,这个动作会触发一次节点删除事件;
若不存在,则说明未失效的主节点不存在,成为主节点;
发生节点删除事件之后,继续判断当前节点是否是最小的排序节点,并循环以上操作;
4.elasticJob的失效转移机制
首先,需要配置开启失效转移;
在作业执行过程中,如果发生实例宕机,则其他实例会监听到实例删除时间;
此时,在leader节点failover节点下会生产对应宕机实例的分片节点;
所有正在执行同一个命名空间的作业的实例都可以来抢这个节点的锁,谁先抢到归谁,这个竞争流程类似于选主流程;
若有多个分片下实例宕机,则每个存活实例,每次失效转移只能竞争一个分片的作业;
失效转移的这一部分作业将在抢到这个分片的实例在完成当前作业后执行;
具体实现:
1.获取第一个失效的分片信息,并创建失效节点;
2.直接抢锁,若抢到,将当前抢到的分片在sharding节点下对应的分片节点的instance改为自己的数据并生成failover节点,标识这个分片需要失效转移;