Elastic-Job
实现分布式下的任务调度,解决以下问题:
-
感觉Spring给我们提供的这个注解可以完成任务调度的功能,好像已经完美解决问题了,为什么还需要分布式呢?
主要有如下这几点原因:
1.单机处理极限:原本1分钟内需要处理1万个订单,但是现在需要1分钟内处理10万个订单;原来一个统计需要1小时,现在业务方需要10分钟就统计出来。你也许会说,你也可以多线程、单机多进程处理。的确,多线程并行处理可以提高单位时间的处理效率,但是单机能力毕竟有限(主要是CPU、内存和磁盘),始终会有单机处理不过来的情况。
2.高可用:单机版的定式任务调度只能在一台机器上运行,如果程序或者系统出现异常就会导致功能不可用。虽然可以在单机程序实现的足够稳定,但始终有机会遇到非程序引起的故障,而这个对于一个系统的核心功能来说是不可接受的。
3.防止重复执行: 在单机模式下,定时任务是没什么问题的。但当我们部署了多台服务,同时又每台服务又有定时任务时,若不进行合理的控制在同一时间,只有一个定时任务启动执行,这时,定时执行的结果就可能存在混乱和错误了
这个时候就需要分布式的任务调度来实现了。
使用
添加依赖
<dependency>
<groupId>com.dangdang</groupId>
<artifactId>elastic-job-lite-spring</artifactId>
<version>2.1.5</version>
</dependency>
配置文件
elasticjob:
zookeeper-url: localhost:2181
group-name: elastic-job-group
spring:
datasource:
url: jdbc:mysql://localhost:3306/elastic-demo?serverTimezone=GMT%2B8
driverClassName: com.mysql.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
username: root
password: admin
主配置类(zookeeper没有自动配置)
@Configuration
public class MyConfig {
@Value("${elasticjob.zookeeper-url}")
private String url;
@Value("{elasticjob.group-name}")
private String groupName;
@Bean
public CoordinatorRegistryCenter registryCenter(){
ZookeeperConfiguration zookeeperConfiguration = new ZookeeperConfiguration(url, groupName);
zookeeperConfiguration.setSessionTimeoutMilliseconds(100);//超时100ms后重新选举
ZookeeperRegistryCenter registryCenter = new ZookeeperRegistryCenter(zookeeperConfiguration);
registryCenter.init();
return registryCenter;
}
}
初始化job类
/*
以下例子实现了分片
"0=text,1=image,2=radio,3=vedio",为固定格式
createLiteJobConfiguration()方法用于生产LiteJobConfiguration的实现类对象
*/
@Configuration
public class JobConfig {
@Autowired
private UpDateFileCustomJob upDateFileCustomJob;
@Autowired
private CoordinatorRegistryCenter registryCenter;
@Autowired
private DataSource dataSource;
@Bean(initMethod = "init")
public SpringJobScheduler springJobScheduler() {
JobEventConfiguration jobEventConfiguration = new JobEventRdbConfiguration(dataSource);
return new SpringJobScheduler(
upDateFileCustomJob,
registryCenter,
createLiteJobConfiguration(FileCustom.class,
"0/3 * * * * ?",
4,
"0=text,1=image,2=radio,3=vedio",
false)
,jobEventConfiguration
);
}
private <T> LiteJobConfiguration createLiteJobConfiguration(Class<T> tClass, String cron, int count, String shardingParameter, boolean dataflowType) {
JobCoreConfiguration.Builder builder = JobCoreConfiguration.newBuilder(tClass.getSimpleName(), cron, count);
if (shardingParameter != null) {
builder.shardingItemParameters(shardingParameter);
}
JobCoreConfiguration coreConfiguration = builder.build();
JobTypeConfiguration jobTypeConfiguration = null;
if (dataflowType) {
jobTypeConfiguration = new DataflowJobConfiguration(coreConfiguration, tClass.getSimpleName(), true);
} else {
jobTypeConfiguration = new SimpleJobConfiguration(coreConfiguration, tClass.getSimpleName());
}
return LiteJobConfiguration.newBuilder(jobTypeConfiguration).overwrite(true).build();
}
}
@Component
public class UpDateFileCustomJob implements SimpleJob {
@Override
public void execute(ShardingContext shardingContext) {
//写执行语句
doWork();
System.out.println("================================");
}
private void doWork(String shardingParameter) {
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("更新" + Thread.currentThread() + new Date());
}
}
分片:将完整的数据按照指定的规则分成多份
对数据进行划分,称为分片规则,