项目因为要分布式部署,所以调研了Elastic Job这个插件,功能很强大,但也有不足的地方有bug,希望作者不断的更新下去。
经过几天的研究,基本使跑起来了,两台pc机,192.168.3.131(跑个两个tomcat),想当于这个机器跑了两个job实例,192.168.3.103(跑了一个tomcat),Elastic Job并没有处理数据分片的功能,数据分片需要用户自己实现。
通过Elastic Job控制台可以很清楚明了的看到当前机器运行的状况。
服务器纬度:

作业纬度:可以很明显的看到你各个机器的实例数

数据分片的逻辑很简单,可以参考Elastic Job源码的服务器分片平均算法。以我当前的例子,我库里有一张表的数据为31数据 ,3台服务器(2个实例+1个机器),3个分片,那么 每个服务就对应一个分片,前两个分片分到的数据则都为10, 最后一个分片分的数据应该为11条,应为有未被整除的数据,这块涉及到 除法和求于运算,有忘记的小伙伴们,自己去翻小学的数学课本吧,废话不多话直接上代码和运行结果,如果有更好的建议,欢迎评论。
@Override
public void execute(ShardingContext context) {
//当前服务器所在的任务分片下标
int shardingItem = context.getShardingItem();
//当任务的分片总数=1时(必须大于0),如果部定时任务工程部署在多个服务器上,则任务将会以1主N从的方式执行。一旦本次执行任务的服务器崩溃,其他执行任务的服务器将会在下次作业启动时选择一个替补执行。如果开启了失效转移,那么功能效果更好,可以保证在本次作业执行时崩溃,备机之一立即启动替补执行
int total=context.getShardingTotalCount();
//查出数量
Map<String,Object> map=new HashMap<>();
List<WxOrderDO> list= payService.getOrderList(map);
if(list!=null&&list.size()>0){
//数据库表有多少条记录
int counts=list.size();
//数据总数要大于分片数据,且分片总数大于1时,采用根据分片下标分页查询,否则分片下标为0的获取所有数据,其他分片不获取数据
if(counts>=total&&total>1){
//平均分页多少条数据
int pageSize=new BigDecimal(counts/total).setScale(0).intValue();
//分配不均的情况下
int pageSizeBin=pageSize;
//把多出的数据加给最后一个分片 即不能整除的数据(余数)分给最后一个分片
if(counts%total>0 && shardingItem==(total-1)) {
pageSizeBin=pageSize+counts%total;
}
Map<String,Object> pageMap=new HashMap<>();
pageMap.put("start",shardingItem*pageSize);
pageMap.put("end",pageSizeBin);
payService.getOrderList(pageMap);
}else{
//分片下标为0的获取所有数据,其他分片不获取数据
Map<String,Object> pageMap=new HashMap<>();
payService.getOrderList(pageMap);
}
}
}
标红框的是3台服务器:

日志打印效果:
第一台日志:

第二台日志:

第三台日志:

本文分享了使用ElasticJob进行分布式任务调度的实践经验,详细解析了数据分片的逻辑与代码实现,适用于多服务器环境下的任务均衡与数据处理。
607





