Spark 离线开发框架设计与实现

news2024/9/19 13:41:41

一、背景

随着 Spark 以及其社区的不断发展,Spark 本身技术也在不断成熟,Spark 在技术架构和性能上的优势越来越明显,目前大多数公司在大数据处理中都倾向使用 Spark。Spark 支持多种语言的开发,如 Scala、Java、Sql、Python 等。

Spark SQL 使用标准的数据连接,与 Hive 兼容,易与其它语言 API 整合,表达清晰、简单易上手、学习成本低,是开发者开发简单数据处理的首选语言,但对于复杂的数据处理、数据分析的开发,使用 SQL 开发显得力不从心,维护成本也非常高,使用高级语言处理会更高效。

在日常的数据仓库开发工作中,我们除了开发工作外,也涉及大量的数据回溯任务。对于创新型业务来说,口径变化频繁、业务迅速迭代,数据仓库的回溯非常常见,通过回溯几个月甚至一年是非常普遍的,但传统的回溯任务方式效率极低,而且需要人力密切关注各任务状态。

针对目前现状,我们开发了一套 Spark 离线开发框架,如下表所示,我们例举了目前存在的问题及解决方案。框架的实现不仅让开发变得简单高效,而且对于数据的回溯工作在不需要任何开发的情况下,快速高效地完成大量的回溯工作。

二、框架设计

框架旨在封装重复的工作,让开发变得简单。框架如图 2-1 所示,主要分为三个部分,基础框架、可扩展工具及应用程序,开发者只需关注应用程序即可简单快速实现代码开发。


2.1 基础框架

基础框架中,我们对于所有类型的应用实现代码与配置分离机制,资源配置统一以 XML 文件形式保存并由框架解析处理。框架会根据开发者配置的任务使用资源大小,完成了 SparkSession、SparkContext、SparkConf 的创建,同时加载了常用环境变量,开发了通用的 UDF 函数(如常用的 url 参数解析等)。其中 Application 为所有应用的父类,处理流程如图所示,开发者只需编写关注绿色部分即可。

目前,离线框架所支持的常用环境变量如下表所示。


2.2 可扩展工具

可扩展工具中包含了大量的工具类,服务于应用程序及基础框架,常用有,配置文件解析类,如解析任务资源参数等;数据库工具类,用于读写数据库;日期工具类,用于日期加减、转换、识别并解析环境变量等。服务于应用程序的通用工具模块可统称为可扩展工具,这里不再赘述。

2.3 应用程序

2.3.1 SQL 应用

对于 SQL 应用,只需要创建 SQL 代码及资源配置即可,应用类为唯一类(已实现),有且只有一个,供所有 SQL 应用使用,开发者无需关心。如下配置所示,class 为所有应用的唯一类名,开发者要关心的是 path 中的 sql 代码及 conf 中该 sql 所使用的资源大小。

<?xml version="1.0" encoding="UTF-8"?>
<project name="test">
    <class>com.way.app.instance.SqlExecutor</class>
    <path>sql文件路径</path>
  <!--    sparksession conf   -->
    <conf>
        <spark.executor.memory>1G</spark.executor.memory>
        <spark.executor.cores>2</spark.executor.cores>
        <spark.driver.memory>1G</spark.driver.memory>
        <spark.executor.instances>20</spark.executor.instances>
    </conf>
</project>

2.3.2 Java 应用

对于复杂的数据处理,SQL 代码不能满足需求时,我们也支持 Java 程序的编写,与 SQL 不同的是,开发者需要创建新的应用类,继承 Application 父类并实现 run 方法即可,run 方法中开发者只需要关注数据的处理逻辑,对于通用的 SparkSession、SparkContext 等创建及关闭无需关注,框架还帮助开发者封装了代码的输入、输出逻辑,对于输入类型,框架支持 HDFS 文件输入、SQL 输入等多种输入类型,开发者只需调用相关处理函数即可。

如下为一个简单的 Java 数据处理应用,从配置文件可以看出,仍需配置资源大小,但与 SQL 不同的是,开发者需要定制化编写对应的 Java 类(class 参数),以及应用的输入(input 参数)和输出参数(output 参数),此应用中输入为 SQL 代码,输出为 HDFS 文件。从 Test 类实现可以看出,开发者只需三步走:获取输入数据、逻辑处理、结果输出,即可完成代码编写。

<?xml version="1.0" encoding="UTF-8"?>
<project name="ecommerce_dwd_hanwuji_click_incr_day_domain">
    <class>com.way.app.instance.ecommerce.Test</class>
    <input>
        <type>table</type>
        <sql>select
            clk_url,
            clk_num
            from test_table
            where event_day='{DATE}'
            and click_pv > 0
            and is_ubs_spam=0
        </sql>
    </input>
    <output>
        <type>afs_kp</type>
        <path>test/event_day={DATE}</path>
    </output>
    <conf>
        <spark.executor.memory>2G</spark.executor.memory>
        <spark.executor.cores>2</spark.executor.cores>
        <spark.driver.memory>2G</spark.driver.memory>
        <spark.executor.instances>10</spark.executor.instances>
    </conf>
</project>
package com.way.app.instance.ecommerce;import com.way.app.Application;import org.apache.spark.api.java.JavaRDD;import org.apache.spark.sql.Row;import java.util.Map;import org.apache.spark.api.java.function.FilterFunction;import org.apache.spark.sql.Dataset;public class Test extends Application {    @Override    public void run() {        // 输入        Map<String, String> input = (Map<String, String>) property.get("input");        Dataset<Row> ds = sparkSession.sql(getInput(input)).toDF("url", "num");        // 逻辑处理(简单的筛选出url带有部分站点的日志)        JavaRDD<String> outRdd = ds.filter((FilterFunction<Row>) row -> {            String url = row.getAs("url").toString();            return url.contains(".jd.com")                    || url.contains(".suning.com")                    || url.contains("pin.suning.com")                      || url.contains(".taobao.com")                    || url.contains("detail.tmall.hk")                    || url.contains(".amazon.cn")                    || url.contains(".kongfz.com")                    || url.contains(".gome.com.cn")                    || url.contains(".kaola.com")                    || url.contains(".dangdang.com")                    || url.contains("aisite.wejianzhan.com")                    || url.contains("w.weipaitang.com");        })                .toJavaRDD()                .map(row -> row.mkString("\001"));        // 输出        Map<String, String> output = (Map<String, String>) property.get("output");        outRdd.saveAsTextFile(getOutPut(output));    }}

2.3.3 数据回溯应用

数据回溯应用是为解决快速回溯、释放人力而研发的,使用非常便捷,开发者无需重构任务代码,与 SQL 应用相同,回溯应用类为唯一类(已实现),有且只有一个,供所有回溯任务使用,且支持多种回溯方案。

2.3.3.1 方案设计

在日常回溯过程中发现,一次回溯任务存在严重的时间浪费,无论以何种方式提交任务,都需要经历以下执行环境申请及准备的过程:

  1. 在 client 提交 application,首先 client 向 RS 申请启动 ApplicationMaster

  2. RS 先随机找到一台 NodeManager 启动 ApplicationMaster

  3. ApplicationMaster 向 RS 申请启动 Executor 的资源

  4. RS 返回一批资源给 ApplicationMaster

  5. ApplicationMaster 连接 Executor

  6. 各个 Executor 反向注册给 ApplicationMaster

  7. ApplicationMaster 发送 task、监控 task 执行,回收结果

这个过程占用的时间我们统称为执行环境准备,我们提交任务后,经历如下三个过程:

  1. 执行环境准备

  2. 开始执行代码

  3. 释放资源

执行环境准备通常会有 5-20 分钟的等待时间,以队列当时的资源情况上下波动,失败率为 10% 左右,失败原因由于队列、网络、资源不足等造成的不可抗力因素;代码执行过程通常失败率在 5% 左右,通常由于节点不稳定、网络等因素导致。离线开发框架回溯应用从节省时间和人力两个方面考虑,设计方案图 2-3 所示。

从回溯时间方面来看:将所有回溯子任务的第一、第三步的时间压缩为一次,即环境准备及释放各一次,执行多次回溯代码。若开发者回溯任务为 30 个子任务,则节省的时间为 5-20 分钟乘 29,可见,回溯子任务越多,回溯提效越明显。

从人工介入方面来看,第一,开发者无需额外开发、添加回溯配置即可。第二,离线框架回溯应用启动的任务数量远远小于传统回溯方案,以图 2-3 为例,该回溯任务为串行回溯方式,使用框架后只需关注一个任务的执行状态,而传统方式则需人工维护 N 个任务的执行状态。

最后,我们在使用离线开发框架回溯一个一年的串行任务中,代码的执行只需要 5 分钟左右,我们发现,不使用离线开发框架回溯的任务在最理想的情况下(即最短时间分配到资源、所有子任务均无失败情况、一次可以串行启动 365 天),需要的时间为 2.5 天,但使用离线开发框架回溯的任务,在最坏的情况下(即最长时间分配到资源,任务失败情况出现 10%),只需要 6 个小时就可完成,提效 90% 以上,且基本无需人力关注。

2.3.3.2 功能介绍

断点续回

使用 Spark 计算,我们在享受其计算带来的飞快速度时,难免会遭遇其中的不稳定性,节点宕机、网络连接失败、资源问题带来的任务失败屡见不鲜,回溯任务动辄几个月、甚至一年,任务量巨大,失败后可以继续从断点处回溯显得尤为重要。在离线框架设计中,记录了任务回溯过程中已成功的部分,任务失败重启后会进行断点续回。

回溯顺序

在回溯任务中,通常我们会根据业务需要确定回溯顺序,如对于有新老用户的增量数据,由于当前的日期数据依赖历史数据,所以我们通常会从历史到现在开始回溯。但没有这种需要时,一般来说,先回溯现在可以快速满足业务方对现在数据指标的了解,我们通常会从现在到历史回溯。在离线框架设计中,开发者可根据业务需要选择回溯顺序。

并行回溯

通常,回溯任务优先级低于例行任务,在资源有限的情况下,回溯过程中不能一次性全部开启,以免占用大量资源影响例行任务,所以离线框架默认为串行回溯。当然在资源充分的时间段,我们可以选择适当的并行回溯。离线开发框架支持一定的并发度,开发者在回溯任务时游刃有余。

2.3.3.3 创建一个回溯任务

回溯应用的使用非常方便,开发者无需新开发代码,使用例行的代码,配置回溯方案即可,如下代码所示,

  • class 参数为回溯应用的唯一类,必填参数,所有回溯任务无需变化。

  • type 参数为回溯应用类型,默认为 sql,若应用类型为 java,则 type 值应为 java 类名。

  • path 参数为回溯代码路径,必填参数,无默认值,通常与例行任务代码相同,无需修改。

  • limitdate 参数为回溯的截止日期,必填参数,无默认值。

  • startdate 参数为回溯开始日期,必填参数,无默认值,若任务进入断点续回或开启并行回溯时,则该参数无效。

  • order 参数为回溯顺序,默认为倒序。当值为 1 时为正序,为值为 - 1 时为倒序。

  • distance 参数为回溯步长,框架默认为串行回溯,但也支持并行回溯,该参数主要用于支持并行回溯,当该参数存在且值不为 - 1 时,回溯开始日期取值为基准日期。如启动两个并行任务,任务的执行范围为基准日期至基准日期加步长或 limitdate,若基准日期加步长后日期大于 limitdate,则是取 limitdate,否则反之。

  • file 参数为回溯日志文件,必填参数,无默认值,用于记录已回溯成功的日期,当失败再次重启任务时,startdate 会以日志文件中日期的下一个日期为准。

  • conf 参数与其他应用相同,为本次回溯任务的资源占用配置。

<?xml version="1.0" encoding="UTF-8"?><project name="ecommerce_ads_others_order_retain_incr_day">    <class>com.way.app.instance.ecommerce.Huisu</class>    <type>sql</type>    <path>/sql/ecommerce/ecommerce_ads_others_order_retain_incr_day.sql</path>    <limitdate>20220404</limitdate>    <startdate>20210101</startdate>    <order>1</order>    <distance>-1</distance>    <file>/user/ecommerce_ads_others_order_retain_incr_day/process</file>    <conf>        <spark.executor.memory>1G</spark.executor.memory>        <spark.executor.cores>2</spark.executor.cores>        <spark.executor.instances>30</spark.executor.instances>        <spark.yarn.maxAppAttempts>1</spark.yarn.maxAppAttempts>    </conf></project>
‍

三、使用方式

3.1 使用介绍

使用离线框架方式开发时,开发者只需重点关注数据逻辑处理部分,开发完成打包后,提交执行,对于每一个应用主类相同,如前文所述为 Application 父类,不随应用变化,唯一变化的是父类需要接收的参数,该参数为应用的配置文件的相对路径。

3.2 使用对比

使用离线框架前后对比图如下所示。


四、展望

目前,离线开发框架仅支持 SQL、Java 语言代码的开发,但 Spark 支持的语言远不止这两种,我们需要继续对框架升级支持多语言开发等,让开发者更方便、快速地进行大数据开发。

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

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

相关文章

亚马逊、OZON、速卖通等跨境电商平台卖家怎样快速提高产品权重?

亚马逊跨境电商是世界顶级的电子商务平台之一。基本上&#xff0c;当80%的客户购买产品时&#xff0c;亚马逊跨境电子商务将成为首选的在线购物平台。亚马逊是一个拥有自己独特优化算法的服务平台&#xff0c;对服务平台上数亿产品进行有序排序。当客户进行产品检索时&#xff…

【附源码】计算机毕业设计JAVA学生宿舍信息管理系统

【附源码】计算机毕业设计JAVA学生宿舍信息管理系统 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; JAVA…

经典排序算法JAVA实现

1、选择排序 首先在未排序数列中找到最小元素&#xff0c;然后将其与数列的首部元素进行交换&#xff0c;然后&#xff0c;在剩余未排序元素中继续找出最小元素&#xff0c;将其与已排序数列的末尾位置元素交换。以此类推&#xff0c;直至所有元素均排序完毕.复杂度为n2&#…

《Java并发编程之美》读书笔记——第一部分(并发编程基础知识)

文章目录第一章 并发编程线程基础1.什么是线程2.线程的创建与运行3.线程的通知与等待wait()wait(long timeout)wait(long timeout, int nanos)notify()与notifyAll()虚假唤醒4.等待线程执行终止的join方法5.让线程睡眠的sleep方法6.让CPU交出执行权的yield方法7.线程中断8.理解…

[附源码]java毕业设计物理中考复习在线考试系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

消息队列卡夫卡+EFLFK集群部署

pache公司的软件包官方下载地址&#xff1a;archive.apache.org/dist/ 注&#xff1a;kafka从3.0版本之后&#xff0c;不再依赖zookeeper。 一 Zookeeper概述 官方下载地址&#xff1a;archive.apache.org/dist/zookee… 1.Zookeeper定义 Zookeeper是一个开源的分布式的&a…

国内网络编译,Ambari 2.7.6 全部模块源码编译笔记

本次编译 ambari 2.7.6 没有使用科学上网的工具&#xff0c;使用的普通网络&#xff0c;可以编译成功&#xff0c;过程比 ambari 2.7.5 编译时要顺畅。 该版本相对 2.7.5 版本以来&#xff0c;共有 26 个 contributors 提交了 114 个 commits 以及修改了 557 个文件。详情见&a…

ovirt-engine通过UI Plugin自定义页面

官方API&#xff1a;点击打开 1 新增一个菜单项 1.1 创建引导html 首先你的这个页面是作为一个功能插件存在的&#xff0c;所以先给他起个名字&#xff0c;我这里的页面主要是用作用户创建&#xff0c;所以我的这个插件的名字就叫user。 接着就创建这个插件的 引导html &…

多级式多传感器信息融合中的状态估计(Matlab代码实现)

&#x1f352;&#x1f352;&#x1f352;欢迎关注&#x1f308;&#x1f308;&#x1f308; &#x1f4dd;个人主页&#xff1a;我爱Matlab &#x1f44d;点赞➕评论➕收藏 养成习惯&#xff08;一键三连&#xff09;&#x1f33b;&#x1f33b;&#x1f33b; &#x1f34c;希…

新能源车提车、上牌流程

漫长等待四个多月&#xff0c;终于2022年10月27日&#xff0c;笔者圆梦&#xff0c;喜提人生第一辆车。从选车、提车、上牌全程一人&#xff0c;用文记录下经历&#xff0c;以供参考。 一、提车流程 1.1 提车时间 若分到车&#xff0c;4S店销售会提前联系确定时间。 提示&…

【自然语言处理】【实体匹配】CollaborER:使用多特征协作的自监督实体匹配框架

CollaborER&#xff1a;使用多特征协作的自监督实体匹配框架《CollaborER: A Self-supervised Entity Resolution Framework Using Multi-features Collaboration》论文地址&#xff1a;https://arxiv.org/pdf/2108.08090.pdf 相关博客&#xff1a; 【自然语言处理】【实体匹配…

最大似然估计(机器学习)

目录 最大似然估计算法 最大似然估计例子 最大似然估计算法存在的问题 最大似然估计算法 EM算法是一种最大似然估计(Max imum Likel ihood Est imation)算法&#xff0c;传统的最大似然估计算法是根据已知的观察数据来评估模型参数 最大似然估计的一般步骤如下&#xff1a; …

HTML小游戏10 —— 休闲类游戏《解救海盗船长》(附完整源码)

&#x1f482; 网站推荐:【神级源码资源网】【摸鱼小游戏】&#x1f91f; 风趣幽默的前端学习课程&#xff1a;&#x1f449;28个案例趣学前端&#x1f485; 想寻找共同学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】&#x1f4ac; 免费且实用的计算机相关知…

kingbase之集群部署之集群规划和安装

一、kingbase简介 KingbaseES是一款面向大规模并发交易处理的企业级关系型数据库。该产品支持严格的ACID特性、结合多核架构的极致性能、行业最高的安全标准&#xff0c;以及完备的高可用方案&#xff0c;并提供可覆盖迁移、开发及运维管理全使用周期的智能便捷工具。在早先的博…

zsh: command not found: adb问题分析

问题描述 Mac上使用 adb 调试Android设备时&#xff0c;出现了 zsh: command not found: adb 的报错提示。 出现上述错误代表 adb 无法在挡枪 的shell 中使用&#xff0c;而当前的 shell 为 zsh 。 zsh 介绍 zsh 也是一种 shell &#xff0c;Unix 衍生系统的默认 的shell 都…

如何使用组件切换器做话题导航

highlight: atelier-cave-dark 使用组件切换器实现一个标签导航 效果展示 前置准备 背景素材 话题图标素材 具体步骤 制作背景 制作话题导航 制作话题导航结果列表 设置组件切换器关联内容 创建切换组件行为触发器 创建点击行为触发器 步骤分解 制作背景 将背景素材添加到 …

Vue使用axios进行get请求拼接参数的两种方式

前言 本文主要介绍如何在Vue使用axios进行get请求拼接参数的两种方式 我们就以github上的一个开源接口举例&#xff1a; https://api.github.com/search/users?qxxx 这是github给开发人员提供的一个接口&#xff0c;是get请求。我们可以直接通过浏览器访问 很明显&#xff…

[附源码]java毕业设计网易云音乐推荐系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

FL Studio21傻瓜式编曲音乐编辑器FL水果软件

在我看来软件只是工具.不管哪个都可以做任何风格的音乐,区别只是软件操作相对而言fl studio更容易上手,在国内也很受欢迎,弱项应该是混音上如果你做电音的话 还是FL更好一些 ,因为他就是为舞曲而生的!flstudio内配置音源、插件、录音软件、混音效果!而FLStudio则更偏向于电子音…

[附源码]SSM计算机毕业设计二手车况在线评估JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…