3. 分片功能讲解
3.1 案例需求:
1.我们现在实现这样的需求,在指定节假日,需要给平台的所有用户去发送祝福的短信
3.2.编码实现:
a.初始化数据
1.在数据库中导入xxl_job_demo.sql
数据
b.集成Druid&MyBatis
< dependency>
< groupId> org.mybatis.spring.boot</ groupId>
< artifactId> mybatis-spring-boot-starter</ artifactId>
< version> 1.2.0</ version>
</ dependency>
< dependency>
< groupId> mysql</ groupId>
< artifactId> mysql-connector-java</ artifactId>
</ dependency>
< dependency>
< groupId> org.projectlombok</ groupId>
< artifactId> lombok</ artifactId>
< scope> provided</ scope>
</ dependency>
< dependency>
< groupId> com.alibaba</ groupId>
< artifactId> druid</ artifactId>
< version> 1.1.10</ version>
</ dependency>
spring.datasource.url=jdbc:mysql://localhost:3306/xxl_job_demo?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.username=root
spring.datasource.password=WolfCode_2017
@Setter @Getter
public class UserMobilePlan {
private Long id;
private String username;
private String nickname;
private String phone;
private String info;
}
@Mapper
public interface UserMobilePlanMapper {
@Select ( "select * from t_user_mobile_plan" )
List < UserMobilePlan > selectAll ( ) ;
}
c.业务功能实现
@XxlJob ( "sendMsgHandler" )
public void sendMsgHandler ( ) throws Exception {
List < UserMobilePlan > userMobilePlans = userMobilePlanMapper. selectAll ( ) ;
System . out. println ( "任务开始时间:" + new Date ( ) + ",处理任务数量:" + userMobilePlans. size ( ) ) ;
Long startTime = System . currentTimeMillis ( ) ;
userMobilePlans. forEach ( item-> {
try {
TimeUnit . MILLISECONDS . sleep ( 10 ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
} ) ;
System . out. println ( "任务结束时间:" + new Date ( ) ) ;
System . out. println ( "任务耗时:" + ( System . currentTimeMillis ( ) - startTime) + "毫秒" ) ;
}
2.任务配置信息
3.3.分片概念讲解
a.举例理解:
1.比如我们的案例中有2000+条数据,如果不采取分片形式的话,任务只会在一台机器上执行,这样的话需要20+秒才能执行完任务. 2.如果采取分片广播的形式的话,一次任务调度将会广播触发对应集群中所有执行器执行一次任务,同时系统自动传递分片参数;可根据分片参数开发分片任务; 3.获取分片参数方式:
int shardIndex = XxlJobHelper . getShardIndex ( ) ;
int shardTotal = XxlJobHelper . getShardTotal ( ) ;
4.通过这两个参数,我们可以通过求模取余的方式,分别查询,分别执行,这样的话就可以提高处理的速度. 5.之前2000+条数据只在一台机器上执行需要20+秒才能完成任务,分片后,有两台机器可以共同完成2000+条数据,每台机器处理1000+条数据,这样的话只需要10+秒就能完成任务
b.案例改造成任务分片
@Mapper
public interface UserMobilePlanMapper {
@Select ( "select * from t_user_mobile_plan where mod(id,#{shardingTotal})=#{shardingIndex}" )
List < UserMobilePlan > selectByMod ( @Param ( "shardingIndex" ) Integer shardingIndex, @Param ( "shardingTotal" ) Integer shardingTotal) ;
@Select ( "select * from t_user_mobile_plan" )
List < UserMobilePlan > selectAll ( ) ;
}
@XxlJob ( "sendMsgShardingHandler" )
public void sendMsgShardingHandler ( ) throws Exception {
System . out. println ( "任务开始时间:" + new Date ( ) ) ;
int shardTotal = XxlJobHelper . getShardTotal ( ) ;
int shardIndex = XxlJobHelper . getShardIndex ( ) ;
List < UserMobilePlan > userMobilePlans = null ;
if ( shardTotal== 1 ) {
userMobilePlans = userMobilePlanMapper. selectAll ( ) ;
} else {
userMobilePlans = userMobilePlanMapper. selectByMod ( shardIndex, shardTotal) ;
}
System . out. println ( "处理任务数量:" + userMobilePlans. size ( ) ) ;
Long startTime = System . currentTimeMillis ( ) ;
userMobilePlans. forEach ( item-> {
try {
TimeUnit . MILLISECONDS . sleep ( 10 ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
} ) ;
System . out. println ( "任务结束时间:" + new Date ( ) ) ;
System . out. println ( "任务耗时:" + ( System . currentTimeMillis ( ) - startTime) + "毫秒" ) ;
}
3.任务设置