Schedulerx2.0分布式计算原理最佳实践

1. 前言

Schedulerx2.0的客户端提供分布式执行、多种任务类型、统一日志等框架,用户只要依赖schedulerx-worker这个jar包,通过schedulerx2.0提供的编程模型,简单几行代码就能实现一套高可靠可运维的分布式执行引擎。

这篇文章重点是介绍基于schedulerx2.0的分布式执行引擎原理和最佳实践,相信看完这篇文章,大家都能写出高效率的分布式作业,说不定速度能提升好几倍:)

2. 可扩展的执行引擎

Worker总体架构参考Yarn的架构,分为TaskMaster, Container, Processor三层:

  • TaskMaster:类似于yarn的AppMaster,支持可扩展的分布式执行框架,进行整个jobInstance的生命周期管理、container的资源管理,同时还有failover等能力。默认实现StandaloneTaskMaster(单机执行),BroadcastTaskMaster(广播执行),MapTaskMaster(并行计算、内存网格、网格计算),MapReduceTaskMaster(并行计算、内存网格、网格计算)。
  • Container:执行业务逻辑的容器框架,支持线程/进程/docker/actor等。
  • Processor:业务逻辑框架,不同的processor表示不同的任务类型。

以MapTaskMaster为例,大概的原理如下图所示:

3. 分布式编程模型之Map模型

Schedulerx2.0提供了多种分布式编程模型,这篇文章主要介绍Map模型(之后的文章还会介绍MapReduce模型,适用更多的业务场景),简单几行代码就可以将海量数据分布式到多台机器上进行分布式跑批,非常简单易用。

针对不同的跑批场景,map模型作业还提供了并行计算、内存网格、网格计算三种执行方式:

  • 并行计算:子任务300以下,有子任务列表。
  • 内存网格:子任务5W以下,无子任务列表,速度快。
  • 网格计算:子任务100W以下,无子任务列表。

4. 并行计算原理

因为并行任务具有子任务列表:


如上图,子任务列表可以看到每个子任务的状态、机器,还有重跑、查看日志等操作。

因为并行计算要做到子任务级别的可视化,并且worker挂了、重启还能支持手动重跑,就需要把task持久化到server端:


如上图所示:

  1. server触发jobInstance到某个worker,选中为master。
  2. MapTaskMaster选择某个worker执行root任务,当执行map方法时,会回调MapTaskMaster。
  3. MapTaskMaster收到map方法,会把task持久化到server端。
  4. 同时,MapTaskMaster还有个pull线程,不停拉取INIT状态的task,并派发给其他worker执行。

5. 网格计算原理

网格计算要支持百万级别的task,如果所有任务都往server回写,server肯定扛不住,所以网格计算的存储实际上是分布式在用户自己的机器上的:

如上图所示:

  1. server触发jobInstance到某个worker,选中为master。
  2. MapTaskMaster选择某个worker执行root任务,当执行map方法时,会回调MapTaskMaster。
  3. MapTaskMaster收到map方法,会把task持久化到本地h2数据库。
  4. 同时,MapTaskMaster还有个pull线程,不停拉取INIT状态的task,并派发给其他worker执行。

6. 最佳实践

6.1 需求

举个例子:

  1. 读取A表中status=0的数据。
  2. 处理这些数据,插入B表。
  3. 把A表中处理过的数据的修改status=1。
  4. 数据量有4亿+,希望缩短时间。

6.2 反面案例

我们先看下如下代码是否有问题?

public class ScanSingleTableProcessor extends MapJobProcessor {private static int pageSize = 1000;@Overridepublic ProcessResult process(JobContext context) {String taskName = context.getTaskName();Object task = context.getTask();if (WorkerConstants.MAP_TASK_ROOT_NAME.equals(taskName)) {int recordCount = queryRecordCount();int pageAmount = recordCount / pageSize;//计算分页数量for(int i = 0 ; i < pageAmount ; i ++) {List<Record> recordList = queryRecord(i);//根据分页查询一页数据map(recordList, "record记录");//把子任务分发出去并行处理}return new ProcessResult(true);//true表示执行成功,false表示失败} else if ("record记录".equals(taskName)) {//TODOreturn new ProcessResult(true);}return new ProcessResult(false);}
}

如上面的代码所示,在root任务中,会把数据库所有记录读取出来,每一行就是一个Record,然后分发出去,分布式到不同的worker上去执行。逻辑是没有问题的,但是实际上性能非常的差。结合网格计算原理,我们把上面的代码绘制成下面这幅图:

如上图所示,root任务一开始会全量的读取A表的数据,然后会全量的存到h2中,pull线程还会全量的从h2读取一次所有的task,还会分发给所有客户端。所以实际上对A表中的数据:

  • 全量读2次
  • 全量写一次
  • 全量传输一次

这个效率是非常低的。

6.3 正面案例

下面给出正面案例的代码:

public class ScanSingleTableJobProcessor extends MapJobProcessor {private static final int pageSize = 100;static class PageTask {private int startId;private int endId;public PageTask(int startId, int endId) {this.startId = startId;this.endId = endId;}public int getStartId() {return startId;}public int getEndId() {return endId;}}@Overridepublic ProcessResult process(JobContext context) {String taskName = context.getTaskName();Object task = context.getTask();if (taskName.equals(WorkerConstants.MAP_TASK_ROOT_NAME)) {System.out.println("start root task");Pair<Integer, Integer> idPair = queryMinAndMaxId();int minId = idPair.getFirst();int maxId = idPair.getSecond();List<PageTask> taskList = Lists.newArrayList();int step = (int) ((maxId - minId) / pageSize); //计算分页数量for (int i = minId; i < maxId; i+=step) {taskList.add(new PageTask(i, (i+step > maxId ? maxId : i+step)));}return map(taskList, "Level1Dispatch");} else if (taskName.equals("Level1Dispatch")) {PageTask record = (PageTask)task;long startId = record.getStartId();long endId = record.getEndId();//TODOreturn new ProcessResult(true);}return new ProcessResult(true);}@Overridepublic void postProcess(JobContext context) {//TODOSystem.out.println("all tasks is finished.");}private Pair<Integer, Integer> queryMinAndMaxId() {//TODO select min(id),max(id) from xxxreturn null;}
}

如上面的代码所示,

  • 每个task不是整行记录的record,而是PageTask,里面就2个字段,startId和endId。
  • root任务,没有全量的读取A表,而是读一下整张表的minId和maxId,然后构造PageTask进行分页。比如task1表示PageTask[1,1000],task2表示PageTask[1001,2000]。每个task处理A表不同的数据。
  • 在下一级task中,如果拿到的是PageTask,再根据id区间去A表处理数据。

根据上面的代码和网格计算原理,得出下面这幅图:

如上图所示,

  • A表只需要全量读取一次。
  • 子任务数量比反面案例少了上千、上万倍。
  • 子任务的body非常小,如果recod中有大字段,也少了上千、上万倍。

综上,对A表访问次数少了好几倍,对h2存储压力少了上万倍,不但执行速度可以快很多,还保证不会把自己本地的h2数据库搞挂。


原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/518830.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

一个优秀的可定制化Flutter相册组件,看这一篇就够了

背景 在做图片、视频相关功能的时候&#xff0c;相册是一个绕不开的话题&#xff0c;因为大家基本都有从相册获取图片或者视频的需求。最直接的方式是调用系统相册接口&#xff0c;基本功能是满足的&#xff0c;一些高级功能就不行了&#xff0c;例如自定义UI、多选图片等。 …

牛客网SQL篇刷题篇(24-31)

https://www.nowcoder.com/ta/sql 1.NOT IN NOT IN运算符允许从结果集中排除特定值的列表。 2.sql子查询 https://www.cnblogs.com/fzxey/p/10896244.html#where%E5%AD%90%E6%9F%A5%E8%AF%A2 子查询就是将一个查询&#xff08;子查询&#xff09;的结果作为另一个查询&…

最近看Kafka源码,着实被它的客户端缓冲池技术优雅到了

作者 | 犀牛饲养员责编 | 徐威龙封图| CSDN 下载于视觉中国最近看kafka源码&#xff0c;着实被它的客户端缓冲池技术优雅到了。忍不住要写篇文章赞美一下&#xff08;哈哈&#xff09;。注&#xff1a;本文用到的源码来自kafka2.2.2版本。背景当我们应用程序调用kafka客户端 pr…

相信坚持的力量,我的程序员打怪升级之路

我是来自阿里云-云通信技术团队的玄照&#xff0c;2015年底进入阿里&#xff0c;刚渡过三年醇&#xff0c;正迈向五年陈的路上。个人兴趣爱好广泛&#xff0c;静的、动的&#xff0c;音乐、游戏、电影、运动都比较喜欢。 玄照&#xff0c;阿里云高级技术专家 程序生涯启航 第…

牛客网SQL篇刷题篇(32-37)

https://www.nowcoder.com/ta/sql 1.sql group_contact()、concat()、concat_ws函数 https://blog.csdn.net/qq_36250202/article/details/99308824 eg:将employees表的所有员工的last_name和first_name拼接起来作为Name&#xff0c;中间以一个空格区分 SELECT CONCAT(las…

支付宝工程师如何搞定关系数据库的“大脑”——查询优化器

前言 查询优化器是关系数据库系统的核心模块&#xff0c;是数据库内核开发的重点和难点&#xff0c;也是衡量整个数据库系统成熟度的“试金石”。 查询优化理论诞生距今已有四十来年&#xff0c;学术界和工业界其实已经形成了一套比较完善的查询优化框架(System-R 的 Bottom-…

SpringBoot2 集成 xxl-job任务调度中心

接上一篇&#xff1a; 搭建xxl-job任务调度中心 https://gblfy.blog.csdn.net/article/details/113809843 文章目录一、SpringBoot 配置1. maven依赖2. 执行器配置 application.yml3. 执行器组件配置4. 部署执行器项目二、xxl-job任务调度中心2.1. 执行器管理2.2. 任务管理三、…

HelloWorld

HelloWorld 创建一个Java文件 文件后缀名为.javaHello.java 编写代码 public class Hello{public static void main(String[] args){System.out.print("Hello, world!");} }编译java文件 javac Hello.java会多出一个Hello.class 文件 运行class文件 java Hell…

运行Java程序时 Tomcat出错 显示端口被占用

解决方法&#xff1a;命令提示符&#xff08;管理员&#xff09; 输入netstat -ano | findstr 8080 检查8080端口有哪些进程 输入taskkill -pid 11728 -f 关闭11728的进程

从开源小白到 Apache Member,我的成长之路

我们走过的每一步路&#xff0c;都会留下印记&#xff0c;越坚实&#xff0c;越清晰。 近日&#xff0c;Apache 软件基金会&#xff08;ASF&#xff09;官方 Blog 宣布全球新增 40 位 Apache Member&#xff0c;张乎兴有幸成为其中一位。 目前&#xff0c;全球共有771位 ASF …

当你打开天猫的那一刻,推荐系统做了哪些工作?

当年打开天猫的那一刻&#xff0c;它为你完成了华丽的变身&#xff0c;成为世上独一无二的“天猫”&#xff0c;这就是智能推荐的力量。今天&#xff0c;来自阿里巴巴搜索推荐事业部的算法工程师陈启伟为你介绍天猫如何玩转首页个性化推荐&#xff0c;揭开搜索推荐的神秘面纱。…

百万人学AI:CSDN重磅共建人工智能技术新生态

站在AI发展的新十年起点上&#xff0c;CSDN将发挥开发者优势&#xff0c;与中国AI各行业和企业共建“百万人学AI”新技术生态。作者 | CSDN新媒体事业部8年前&#xff0c;现图灵奖得主Hinton团队在ImageNet竞赛中首次使用深度学习完胜Google等其它团队&#xff0c;顿时让工业界…

牛客网SQL篇刷题篇(38-47)

1.视图&#xff1a;视图是可视化的表。 视图的作用&#xff1a; 第一点&#xff1a;使用视图&#xff0c;可以定制用户数据&#xff0c;聚焦特定的数据。 解释&#xff1a; 在实际过程中&#xff0c;公司有不同角色的工作人员&#xff0c;我们以销售公司为例的话&#xff0…

SpringBoot2 集成 xxl-job任务调度中心_参数传递

文章目录一、xxl-job任务调度中心1. 调度中心创建任务2. 调度中心创建执行器二、执行器任务编码2.1. 单参数2.2. 多参数三、调度中心参数传递测试3.1. 单个参数传递3.2. 多个参数传递前提&#xff1a;执行器和xxl-job任务调度中心启动完毕 一、xxl-job任务调度中心 1. 调度中心…

Java-用IDEA创建Java项目

1. 创建项目 2. 创建空项目 3. 输入项目名 &#xff14;.配置JDK 点击Project Structure 配置JDK 点击Apply->OK 5. 新建模块 https://www.bilibili.com/video/BV12J41137hu?p21&spm_id_frompageDriver

DevOps:从「蒸汽时代」到「高铁时代」,SUNMI DevOps转型之路 | 原力计划

作者 | 文振熙、刘文沣责编 | 徐威龙封图| CSDN 下载于视觉中国商米科技成立于 2013 年&#xff0c;总部位于上海市杨浦区创智天地&#xff0c;是一家具有产品创新基因和互联网基因的公司。商米在短时间内迅速成长为一家近1000人的企业&#xff0c;产品研发人数占比一度超过70%…

SpringBoot2 集成 xxl-job任务调度中心_路由策略

文章目录一、简述二、故障转移演示2.1. 启动2个执行器2.2. 添加执行器ip2.3. 故障转移策略2.4. 启动任务2.5. 模拟8081执行器宕机2.6. 结论三、轮训策略演示3.1. 启动2个执行器3.2. 添加执行器ip3.3. 轮训策略3.4. 启动任务3.5. 日志分析3.6. 故障转移3.7. 重新启动8082执行器四…

Uniapp组件之间传参

1.父组件内引入子组件&#xff0c;并且子组件使用父组件内的数据 将子组件引入到父组件&#xff1a; <uni-pop :opts"defaultOptions"></uni-pop> import uniPop from /components/uniPop/uniPop.vue 子组件使用父组件内的数据&#xff1a; 2------创建…

基于大数据的舆情分析系统架构 - 架构篇

前言 互联网的飞速发展促进了很多新媒体的发展&#xff0c;不论是知名的大V&#xff0c;明星还是围观群众都可以通过手机在微博&#xff0c;朋友圈或者点评网站上发表状态&#xff0c;分享自己的所见所想&#xff0c;使得“人人都有了麦克风”。不论是热点新闻还是娱乐八卦&am…

Java-标识符和关键字

关键字 标识符 https://www.bilibili.com/video/BV12J41137hu?p22&spm_id_frompageDriver