前言
数据分片的目的在于把一个任务分散到不同的机器上运行,既可以解决单机计算能力上限的问题,也能降低部分任务失败对整体系统的影响。elastic-job并不直接提供数据处理的功能,框架只会将分片项分配至各个运行中的作业服务器,开发者需要自行处理分片项与真实数据的对应关系。框架也预置了一些分片策略:平均分配算法策略,作业名哈希值奇偶数算法策略,轮转分片策略。同时也提供了自定义分片策略的接口。
调度模型
与大部分的作业平台不同,ElasticJob 的调度模型划分为支持线程级别调度的进程内调度 ElasticJob-Lite,和进程级别调度的 ElasticJob-Cloud。
-
进程内调度(推荐)
ElasticJob-Lite 是面向进程内的线程级调度框架。通过它,作业能够透明化的与业务应用系统相结合。 它能够方便的与 Spring 、Dubbo 等 Java 框架配合使用,在作业中可自由使用 Spring 注入的 Bean,如数据源连接池、Dubbo 远程服务等,更加方便的贴合业务开发。 -
进程级调度
独立布署,能够对作业服务器的资源进行控制,因此其作业类型可划分为常驻任务和瞬时任务。
Demo案例
根据官文档简写demo如下
//启动类
public final class JavaMain {
private static final int EMBED_ZOOKEEPER_PORT = 2181;
private static final String ZOOKEEPER_CONNECTION_STRING = "localhost:" + EMBED_ZOOKEEPER_PORT;
private static final String JOB_NAMESPACE = "elasticjob-example-lite-java";
private static final String EVENT_RDB_STORAGE_DRIVER = "org.h2.Driver";
private static final String EVENT_RDB_STORAGE_URL = "jdbc:h2:mem:job_event_storage";
private static final String EVENT_RDB_STORAGE_USERNAME = "sa";
private static final String EVENT_RDB_STORAGE_PASSWORD = "";
public static void main(final String[] args) throws IOException {
//设置机器网卡,用来确定本机的唯一性
System.setProperty("elasticjob.preferred.network.interface", "en0");
//连接zk
CoordinatorRegistryCenter regCenter = setUpRegistryCenter();
//Tracing配置,通知形式记录任务调用过程
TracingConfiguration<DataSource> tracingConfig = new TracingConfiguration<>("RDB", setUpEventTraceDataSource());
//设置一个简单的任务
setUpSimpleJob(regCenter, tracingConfig);
}
private static CoordinatorRegistryCenter setUpRegistryCenter() {
ZookeeperConfiguration zkConfig = new ZookeeperConfiguration(ZOOKEEPER_CONNECTION_STRING, JOB_NAMESPACE);
CoordinatorRegistryCenter result = new ZookeeperRegistryCenter(zkConfig);
result.init();
return result;
}
private static DataSource setUpEventTraceDataSource() {
BasicDataSource result = new BasicDataSource();
result.setDriverClassName(EVENT_RDB_STORAGE_DRIVER);
result.setUrl(EVENT_RDB_STORAGE_URL);
result.setUsername(EVENT_RDB_STORAGE_USERNAME);
result.setPassword(EVENT_RDB_STORAGE_PASSWORD);
return result;
}
private static void setUpSimpleJob(final CoordinatorRegistryCenter regCenter, final TracingConfiguration<DataSource> tracingConfig) {
new ScheduleJobBootstrap(regCenter, new JavaSimpleJob(), JobConfiguration.newBuilder("javaSimpleJob", 3)
.cron("0/5 * * * * ?").shardingItemParameters("0=Beijing,1=Shanghai,2=Guangzhou").build(), tracingConfig).schedule();
}
}
//具体的任务
public class JavaSimpleJob implements SimpleJob {
@Override
@SneakyThrows
public void execute(final ShardingContext shardingContext) {
System.out.println(String.format("Item: %s | Time: %s | Thread: %s | %s",
shardingContext.getShardingItem(), new SimpleDateFormat("HH:mm:ss").format(new Date()), Thread.currentThread().getId(), "SIMPLE"));
Thread.sleep(80000);
}
}
zk中注册数据如下

elastic-job原理
elastic-job的是通过zookeeper来实现的。从zookeeper数据看elastic-job是以任务为维度。任务和任务之间隔理的。
执行原理
elastic-job各节点读取配置文件,封装自己的ElasticJob注入Quazrt定时器框架,然后通过选主,分片等判断,最终执行JavaSimpleJob。


选主原理
选主主要通过zk机制选取,其原理请参考《分布式事务与一致性》。代码如是
//ElasticJobExecutor.execute (将Quazrt转为ElasticJob逻辑入口)
//LiteJobFacade.getShardingContexts
//ShardingService.shardingIfNecessary
public void shardingIfNecessary() {
//循环选主
if (!leaderService.isLeaderUntilBlock()) {
blockUntilShardingCompleted();
return;
}
//等待进行中任务全部执行完毕,如果之前有任务还没跑完,全开始等待
waitingOtherShardingItemCompleted();
JobConfiguration jobConfig = configService.load(false);
int shardingTotalCount = jobConfig.getShardingTotalCount();
log.debug("Job '{}' sharding begin.", jobName);
jobNodeStorage.fillEphemeralJobNode(ShardingNode.PROCESSING, "");
resetShardingInfo(shardingTotalCount);
JobShardingStrategy jobShardingStrategy = JobShardingStrategyFactory.getStrategy(jobConfig.getJobShardingStrategyType());
//根据分片策略重新分片,然后结束选举,其它不是leader结点不用阻塞在选主那
jobNodeStorage.executeInTransaction(new PersistShardingInfoTransactionExecutionCallback(jobShardingStrategy.sharding(availableJobInstances, jobName, shardingTotalCount)));
log.debug("Job '{}' sharding complete.", jobName);
}
总结
- elastic-job通过代理Quazrt实现。
- 新的Job实例加入集群,现有的Job实例下线都会触发重新选举
- 发生重新选举时,如果发现还有任务在跑,会等待其跑完,再重新分片
ElasticJob 是一款分布式调度框架,支持数据分片和弹性伸缩。它通过 ZooKeeper 实现作业集群间的协调与分片,适用于大规模数据处理场景。本文介绍 ElasticJob 的核心概念、分片策略及调度模型。

1287

被折叠的 条评论
为什么被折叠?



