Map
含义
Map模式相对于静态分片是类似的,区别就在于静态分片是一开始就配置好分片了,而Map则是根据代码逻辑进行分片
场景
假设现在有一个每日处理数据的需求但是数据量不定,这个时候我们就可以通过Map来进行处理。
假设公司要对明文保存手机号的 User
表进行数据安全审查,数据量不定,通过 snail-job
的Map任务将这些数据按不同范围分片处理。
测试
测试目的
- 验证是否可以按照代码逻辑进行分片
- 验证分片后其中一片的数据执行失败会是怎样的结果
测试代码
java
@Component
@JobExecutor(name = "testMapJobExecutor")
public class TestMapJobExecutor {
private final Integer BATCH_SIZE = 3;
@MapExecutor
public ExecuteResult rootMapExecute(MapArgs mapArgs, MapHandler mapHandler) {
// 此处可以进行自定义的分片逻辑
List<String> phones = JSON.parseArray(String.valueOf(mapArgs.getJobParams()), String.class);
List<List<String>> partition = Lists.partition(phones, BATCH_SIZE);
// 服务端会获取到客户端的节点数量来处理map的各个分片
// 根据在页面配置的路由策略,把对应的分片分发到不同客户端节点
// 例如:入参总量为10条,BATCH_SIZE设置为3则每3条一个分组,分组结果(List<T> taskList)为[{0,3}, {4, 6}, {7,9}, {10}],此时就会分为四组
// 集合中的各个对象都会作为MapArgs的mapResult参数传递到后续的各个Map任务中
// 此处的nextTaskName即为后续分发的Map任务名称
return mapHandler.doMap(partition, "SECOND_MAP");
}
// 由ROOT_MAP分片分发到SECOND_MAP任务
@MapExecutor(taskName = "SECOND_MAP")
public ExecuteResult secondMapExecute(MapArgs mapArgs) {
SnailJobLog.REMOTE.info(JSON.toJSONString(mapArgs.getMapResult()));
// mapResult 即为上述分包中分发下来的具体参数
// 各节点分别处理分片后的业务逻辑
// 测试目的2时取消注释
//List<String> strings = JSON.parseArray(JSON.toJSONString(mapArgs.getMapResult()), String.class);
//if (strings.contains("5")){
// int i = 1/0;
//}
return ExecuteResult.success("执行结果");
}
}
idea启动多个节点配置
shell
server.port=web端口 spring.profiles.active=执行环境
-Dserver.port=9901 -Dspring.profiles.active=dev-one
-Dserver.port=9902 -Dspring.profiles.active=dev-two
-Dserver.port=9903 -Dspring.profiles.active=dev-three
同时启动3个节点
测试结果
目的一结果:开始只有一个Root节点接收到参数,Root节点根据逻辑将数据进行分片再交给Sec节点处理
- Root节点
![](/sj_job_config_image/19.png)
- Sec节点
目的二结果:分片后其中一片的数据执行失败整个批次即为失败
结论
- Map类型相比静态分片类型会比较动态,可以在代码中将分片逻辑预处理掉,这样就可以避免未知数据量时无法提前进行分片的问题