任务调度之Oozie详解

article/2025/9/16 21:48:25

 利用shell脚本通过crontab进行定时执行,这样实现的话比较简单,但是随着多个job复杂度的提升,无论是协调工作还是任务监控都变得麻烦,我们选择使用oozie来对工作流进行调度监控。

1. Oozie的特点

  • Oozie是管理hadoop作业的调度系统
  • Oozie的工作流作业是一系列动作的有向无环图(DAG)
  • Oozie协调作业是通过时间(频率)和有效数据触发当前的Oozie工作流程
  • Oozie支持各种hadoop作业,例如:java map-reduce、Streaming map-reduce、pig、hive、sqoop和distcp等等,也支持系统特定的作业,例如java程序和shell脚本。
  • Oozie是一个可伸缩,可靠和可拓展的系统

2. 为什么选择Oozie

 在没有工作流调度系统之前,公司里面的任务都是通过 crontab 来定义的,时间长了后会发现很多问题:

1.大量的crontab任务需要管理
2.任务没有按时执行,各种原因失败,需要重试
3.多服务器环境下,crontab分散在很多集群上,光是查看log就很花时间

 于是,出现了一些管理crontab任务的调度系统,如 CronHub、CronWeb 等。
而在大数据领域,现在市面上常用的工作流调度工具有Oozie, Azkaban,Cascading,Hamake等,

我们往往把 Oozie和Azkaban来做对比:
 两者在功能方面大致相同,只是Oozie底层在提交Hadoop Spark作业是通过org.apache.hadoop的封装好的接口进行提交,而Azkaban可以直接操作shell语句。在安全性上可能Oozie会比较好。

  • 工作流定义: Oozie是通过xml定义的而Azkaban为properties来定义。
  • 部署过程: Oozie的部署相对困难些,同时它是从Yarn上拉任务日志。
  • 任务检测: Azkaban中如果有任务出现失败,只要进程有效执行,那么任务就算执行成功,这是BUG,但是Oozie能有效的检测任务的成功与失败。
  • 操作工作流: Azkaban使用Web操作。Oozie支持Web,RestApi,Java API操作。
  • 权限控制: Oozie基本无权限控制,Azkaban有较完善的权限控制,供用户对工作流读写执行操作。
  • 运行环境: Oozie的action主要运行在hadoop中而Azkaban的actions运行在Azkaban的服务器中。
  • 记录workflow的状态: Azkaban将正在执行的workflow状态保存在内存中,Oozie将其保存在Mysql中。
  • 出现失败的情况: Azkaban会丢失所有的工作流,但是Oozie可以在继续失败的工作流运行

3. Oozie-Azkaban详细对比

 对市面上最流行的两种调度器,给出以下详细对比。知名度比较高的应该是Apache Oozie,但是其配置工作流的过程是编写大量的XML配置,而且代码复杂度比较高,不易于二次开发。ooize相比azkaban是一个重量级的任务调度系统,功能全面,但配置使用也更复杂。如果可以不在意某些功能的缺失,轻量级调度器azkaban是很不错的候选对象。

从功能上来对比
  两者均可以调度linux命令、mapreduce、spark、pig、java、hive、java程序、脚本工作流任务
  两者均可以定时执行工作流任务

从工作流定义上来对比
  1、Azkaban使用Properties文件定义工作流
  2、Oozie使用XML文件定义工作流

从工作流传参上来对比
  1、Azkaban支持直接传参,例如${input}
  2、Oozie支持参数和EL表达式,例如${fs:dirSize(myInputDir)}

从定时执行上来对比
  1、Azkaban的定时执行任务是基于时间的
  2、Oozie的定时执行任务基于时间和输入数据

从资源管理上来对比
  1、Azkaban有较严格的权限控制,如用户对工作流进行读/写/执行等操作
  2、Oozie暂无严格的权限控制

从工作流执行上来对比
  1、Azkaban有三种运行模式:
    1.1、solo server mode:最简单的模式,数据库内置的H2数据库,管理服务器和执行服务器都在一个进程中运行,任务量不大项目可以采用此模式。
    1.2、 two server mode:数据库为mysql,管理服务器和执行服务器在不同进程,这种模式下,管理服务器和执行服务器互不影响
    1.3 、multiple executor mode:该模式下,执行服务器和管理服务器在不同主机上,且执行服务器可以有多个
    我这次采用第二种模式,管理服务器、执行服务器分进程,但在同一台主机上。
  2、Oozie作为工作流服务器运行,支持多用户和多工作流

从工作流管理上来对比
  1、Azkaban支持浏览器以及ajax方式操作工作流
  2、Oozie支持命令行、HTTP REST、Java API、浏览器操作工作流

另一版本区别:
  两者在功能方面大致相同,只是Oozie底层在提交Hadoop Spark作业是通过org.apache.hadoop的封装好的接口进行提交,而Azkaban可以直接操作shell语句。在安全性上可能Oozie会比较好。
  工作流定义:Oozie是通过xml定义的而Azkaban为properties来定义。
  部署过程: Oozie的部署太虐心了。有点难。同时它是从Yarn上拉任务日志。
        Azkaban中如果有任务出现失败,只要进程有效执行,那么任务就算执行成功,这是BUG,但是Oozie能有效的检测任务的成功与失败。
  操作工作流:Azkaban使用Web操作。Oozie支持Web,RestApi,Java API操作。
  权限控制: Oozie基本无权限控制,Azkaban有较完善的权限控制,入用户对工作流读写执行操作。
        Oozie的action主要运行在hadoop中而Azkaban的actions运行在Azkaban的服务器中。
  记录workflow的状态:Azkaban将正在执行的workflow状态保存在内存中,Oozie将其保存在Mysql中。
  出现失败的情况:Azkaban会丢失所有的工作流,但是Oozie可以在继续失败的工作流运行。

4. 主要概念

 我们在官网介绍中就注意到了,Oozie主要有三个主要概念,分别是 workflow,coordinator,bundle。
在这里插入图片描述
其中:
Workflow:工作流,由我们需要处理的每个工作组成,进行需求的流式处理。
Coordinator:协调器,可以理解为工作流的协调器,可以将多个工作流协调成一个工作流来进行处理。
Bundle:捆,束。将一堆的coordinator进行汇总处理。

 简单来说,workflow是对要进行的顺序化工作的抽象,coordinator是对要进行的顺序化的workflow的抽象,bundle是对一堆coordiantor的抽象。层级关系层层包裹。
Oozie本质是通过 launcher job 运行某个具体的Action。launcher job是一个MR作业,而且并不知道它将在集群的哪台机器上执行这个MR作业。

5. Job组成

一个oozie 的 job 一般由以下文件组成:
job.properties :记录了job的属性
workflow.xml :使用hPDL 定义任务的流程和分支
lib目录:用来执行具体的任务

5.1 Job.properties

KEY含义
nameNodeHDFS地址
jobTrackerjobTracker(ResourceManager)地址
queueNameOozie队列(默认填写default)
examplesRoot全局目录(默认填写examples)
oozie.usr.system.libpath是否加载用户lib目录(true/false)
oozie.libpath用户lib库所在的位置
oozie.wf.application.pathOozie流程所在hdfs地址(workflow.xml所在的地址)
user.name当前用户
oozie.coord.application.pathCoordinator.xml地址(没有可以不写)
oozie.bundle.application.pathBundle.xml地址(没有可以不写)

5.2 workflow.xml

这个文件是定义任务的整体流程的文件,官网wordcount例子如下:
在这里插入图片描述

<workflow-app name='wordcount-wf' xmlns="uri:oozie:workflow:0.1"><start to='wordcount'/><action name='wordcount'><map-reduce><job-tracker>${jobTracker}</job-tracker><name-node>${nameNode}</name-node><configuration><property><name>mapred.mapper.class</name><value>org.myorg.WordCount.Map</value></property><property><name>mapred.reducer.class</name><value>org.myorg.WordCount.Reduce</value></property><property><name>mapred.input.dir</name><value>${inputDir}</value></property><property><name>mapred.output.dir</name><value>${outputDir}</value></property></configuration></map-reduce><ok to='end'/><error to='kill'/></action><kill name='kill'><message>Something went wrong: ${wf:errorCode('wordcount')}</message></kill/><end name='end'/>
</workflow-app>

**[控制流节点]:主要包括start、end、fork、join等,其中fork、join成对出现,在fork展开。分支,最后在join结点汇聚
  ** start
  ** kill
  ** end
**[动作节点]:包括Hadoop任务、SSH、HTTP、EMAIL、OOZIE子任务
  ** ok --> end
  ** error --> kill
  ** 定义具体需要执行的job任务
  ** MapReduce、shell、hive

注意:
 文件需要被放在HDFS上才能被oozie调度,如果在启动需要调动MR任务,jar包同样需要在hdfs上

Lib目录:
 在workflow工作流定义的同级目录下,需要有一个lib目录,在lib目录中存在java节点MapReduce使用的jar包。

 需要注意的是,oozie并不是使用指定jar包的名称来启动任务的,而是通过制定主类来启动任务的。在lib包中绝对不能存在某个jar包的不同版本,不能够出现多个相同主类。

6. Workflow介绍

在这里插入图片描述
 workflow 是一组 actions 集合(例如Hadoop map/reduce作业,pig作业),它被安排在一个控制依赖项DAG(Direct Acyclic Graph)中。“控制依赖”从一个action到另一个action意味着第二个action不能运行,直到第一个action完成。
 Oozie Workflow 定义是用 hPDL 编写的(类似于JBOSS JBPM jPDL的XML过程定义语言)。
 Oozie Workflow actions在远程系统(如Hadoop、Pig)中启动工作。在action完成时,远程系统回调 Oozie通知action完成,此时Oozie将继续在workflow中进行下一步操作。
 Oozie Workflow 包含控制流节点(control flow nodes)和动作节点(action nodes).
控制流节点定义workflow的开始和结束(start、end 和 fail 节点),并提供一种机制来控制workflow执行路径(decision、fork和join节点)。
 action 节点是workflow触发计算/处理任务执行的机制。Oozie为不同类型的操作提供了支持:Hadoop map-reduce、Hadoop文件系统、Pig、SSH、HTTP、电子邮件和Oozie子工作流。Oozie可以扩展来支持其他类型的操作。
 Oozie Workflow 可以被参数化(在工作流定义中使用诸如$inputDir之类的变量)。在提交workflow作业值时,必须提供参数。如果适当地参数化(即使用不同的输出目录),几个相同的workflow作业可以并发。

7. Coordinator介绍

在这里插入图片描述
 用户通常在grid上运行map-reduce、hadoop流、hdfs或pig作业。这些作业中的多个可以组合起来形成一个workflow 作业。Hadoop workflow 系统定义了一个workflow 系统来运行这样的工作。
 通常,workflow 作业是基于常规的时间间隔(time intervals)和数据可用性(data availability)运行的。在某些情况下,它们可以由外部事件触发。
 表示触发workflow 作业的条件可以被建模为必须满足的谓词(predicate )。workflow 作业是在谓词满足之后开始的。谓词可以引用数据、时间和/或外部事件。在将来,可以扩展模型来支持额外的事件类型。
 还需要连接定期运行的workflow 作业,但在不同的时间间隔内。多个后续运行的workflow 的输出成为下一个workflow 的输入。例如,每15分钟运行一次的workflow 的4次运行的输出,就变成了每隔60分钟运行一次的workflow 的输入。将这些workflow 链接在一起会导致它被称为数据应用程序管道。
 Oozie Coordinator 系统允许用户定义和执行周期性和相互依赖的workflow 作业(数据应用程序管道)。

8. Bundle介绍

在这里插入图片描述
 Bundle 是一个更高级的oozie抽象,它将批处理一组Coordinator应用程序。
 用户将能够在bundle级别启动/停止/暂停/恢复/重新运行,从而获得更好、更容易的操作控制。
 更具体地说,oozie Bundle系统允许用户定义和执行一堆通常称为数据管道的Coordinator应用程序。在Bundle中,Coordinator应用程序之间没有显式的依赖关系。然而,用户可以使用Coordinator应用程序的数据依赖来创建隐式数据应用程序管道。

9. 案例演示

配置文件1:coordinator.xml
在这里插入图片描述
配置文件2:workflow.xml
在这里插入图片描述
配置文件3:job.properties
在这里插入图片描述
[补充]crontab执行时间计算:
各个字符代表的含义。0代表从0分开始,*代表任意字符,/代表递增。
crontab执行时间计算
Cron表达式生成器
在这里插入图片描述

将配置文件和jar包按照配置文件中配置的路径上传到HDFS的对应目录
注:严格注意目录位置
在这里插入图片描述

9.1 测试-步骤:

#在HDFS上建立如下文件夹
hdfs dfs -mkdir -p /apps/tags/models/Tag_001/lib
#将文件上传到HDFS
hdfs dfs -put job.properties /apps/tags/models/Tag_001/
hdfs dfs -put coordinator.xml /apps/tags/models/Tag_001/
hdfs dfs -put workflow.xml /apps/tags/models/Tag_001/
hdfs dfs -put model29.jar /apps/tags/models/Tag_001/lib

9.2 Oozie命令

在服务器中cd oozie_test/查看
coordinator.xml\job.properties\model29.jar\workflow.xml

#运行oozie coordinator.xml
#校验配置文件
oozie validate -oozie http://bd001:11000/oozie /root/oozie_test/coordinator.xml
#运行job(配置文件在/root/oozie_test/job.properties,需要查看服务器是否有改文件)
oozie job -oozie http://bd001:11000/oozie -config /root/oozie_test/job.properties -run
#查看信息
oozie job -oozie http://bd001:11000/oozie -info 0000029-191027171933033-oozie-root-C
#查看日志
oozie job -oozie http://bd001:11000/oozie -log 0000064-190923225831711-oozie-root-C
#Kill任务
oozie job -oozie http://bd001:11000/oozie -kill 0000064-190923225831711-oozie-root-C
#查看所有普通任务
oozie  jobs  -oozie http://bd001:11000/oozie
#查看定时任务
oozie jobs -jobtype coordinator -oozie http://bd001:11000/oozie

结果截图:
在这里插入图片描述
Web:http://bd001:11000/oozie/部分查看
思考:上述通过命令调度,在项目中整合oozieAPI整合SpringBoot完成调度

10. Oozie工具类代码开发

导入Oozie相关配置文件,放入resources文件夹
以下文件是up.conf

model: {user: "root"app: "tags"path: {jars: "/temp/jars"model-base: "/apps/tags_new/models"}
}
hadoop: {name-node: "hdfs://bd001:8020"resource-manager: "bd001:8032"
}
mysql: {url: "jdbc:mysql://bd001:3306/tags_new?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC&user=root&password=123456"driver: "com.mysql.jdbc.Driver"tag-table: "tbl_basic_tag"model-table: "tbl_model"
}
oozie: {url: "http://bd001:11000/oozie"params: {"user.name": ${model.user}"nameNode": ${hadoop.name-node}"jobTracker": ${hadoop.resource-manager}"appName": ${model.app}"master": "yarn""mode": "cluster""queueName": "default""oozie.use.system.libpath": "true""oozie.libpath": "${nameNode}/user/root/share/lib/lib_20190802113508/spark2""sparkOptions": " --driver-memory 512m --executor-memory 512m --num-executors 1 --executor-cores 1 --conf spark.yarn.historyServer.address=http://bd001:18081 --conf spark.eventLog.enabled=true --conf spark.eventLog.dir=hdfs://bd001:8020/apps/spark2/spark2-history/ --conf spark.yarn.jars=hdfs://bd001:8020/apps/archive/sparklib/spark-libs.jar""freq": "0/10 * * * *"}
}

10.1 编写Oozie配置类

ConfigHolder.scala

package com.erainm.up.commonimport com.typesafe.config.ConfigFactory
import pureconfig.ConfigSource
case class Config
(model: Model,hadoop: Hadoop,mysql: MySQL,oozie: Oozie
)case class Model
(user: String,app: String,path: Path
)case class Path
(jars: String,modelBase: String
)case class Hadoop
(nameNode: String,resourceManager: String
)case class MySQL
(url: String,driver: String,tagTable: String,modelTable: String
)case class Oozie
(url: String,params: Map[String, String]
)object ConfigHolder {import pureconfig._import pureconfig.generic.auto._private val configTool = ConfigFactory.load("up")val config: Config = ConfigSource.fromConfig(configTool).load[Config].right.getval model: Model = config.modelval hadoop: Hadoop = config.hadoopval oozie: Oozie = config.oozieval mysql: MySQL = config.mysql
}

10.2 编写Oozie工具类

OozieUtils.scala 编写

package com.erainm.up.commonimport java.util.Properties
import org.apache.commons.lang3.StringUtils
import org.apache.oozie.client.OozieClientobject OozieUtils {val classLoader: ClassLoader = getClass.getClassLoader/*** Properties 包含各种配置* OozieParam 外部传进来的参数* 作用: 生成配置, 有些配置无法写死, 所以外部传入*/def genProperties(param: OozieParam): Properties = {val properties = new Properties()val params: Map[String, String] = ConfigHolder.oozie.paramsfor (entry <- params) {properties.setProperty(entry._1, entry._2)}val appPath = ConfigHolder.hadoop.nameNode + genAppPath(param.modelId)properties.setProperty("appPath", appPath)properties.setProperty("mainClass", param.mainClass)properties.setProperty("jarPath", param.jarPath) // 要处理if (StringUtils.isNotBlank(param.sparkOptions)) properties.setProperty("sparkOptions", param.sparkOptions)properties.setProperty("start", param.start)properties.setProperty("end", param.end)properties.setProperty(OozieClient.COORDINATOR_APP_PATH, appPath)properties}/*** 上传配置* @param modelId 因为要上传到 家目录, 所以要传入 id 生成家目录*/def uploadConfig(modelId: Long): Unit = {val workflowFile = classLoader.getResource("oozie/workflow.xml").getPathval coordinatorFile = classLoader.getResource("oozie/coordinator.xml").getPathval path = genAppPath(modelId)HDFSUtils.getInstance().mkdir(path)HDFSUtils.getInstance().copyFromFile(workflowFile, path + "/workflow.xml")HDFSUtils.getInstance().copyFromFile(coordinatorFile, path + "/coordinator.xml")}def genAppPath(modelId: Long): String = {ConfigHolder.model.path.modelBase + "/tags_" + modelId}def store(modelId: Long, prop: Properties): Unit = {val appPath = genAppPath(modelId)prop.store(HDFSUtils.getInstance().createFile(appPath + "/job.properties"), "")}def start(prop: Properties): Unit = {val oozie = new OozieClient(ConfigHolder.oozie.url)println(prop)val jobId = oozie.run(prop)println(jobId)}/*** 调用方式展示*/def main(args: Array[String]): Unit = {val param = OozieParam(19,"com.erainm.up29.TestTag","hdfs://bd001:8020/apps/tags/models/Tag_001/lib/model29.jar","","2019-09-24T06:15+0800","2030-09-30T06:15+0800")val prop = genProperties(param)println(prop)uploadConfig(param.modelId)store(param.modelId, prop)start(prop)}
}case class OozieParam
(modelId: Long,mainClass: String,jarPath: String,sparkOptions: String,start: String,end: String
)

10.3 编写Oozie测试类

package com.erainm.up.commonimport java.util.Properties
import org.apache.oozie.client.OozieClient
object OozieTest {def upload (): Unit = {}def genProperties(): Unit = {}def main(args: Array[String]): Unit = {// 1. 上传文件到 HDFS 中, workflow.xml, coordinator.xml, jarval path = getClass.getResource("oozie/workflow.xml").getPathHDFSUtils.getInstance().copyFromFile(path, "/apps/tags_new/models/tags_modelid")// 2. 创建配置// 2.1. 读取配置, 这些配置可能不变, 写死的val prop = new Properties()prop.load(getClass.getResource("oozie/job.properties").openStream())// 2.2. 有一些参数, 必须要不同的模型计算, 有不同的值// prop.setProperty(...)// 3. 运行 Oozie 任务, oozie -oozie ... -config job.properties -runval client = new OozieClient("http://bd001:11000/oozie")// run -> submit + startclient.run(prop)}
}

 注意:有时候oozie调度会因为windows和服务器时间不一致,使用 date -s "2020-09-08 11:07:00"修改

11. Oozie整合SpringBoot编写任务调度【测试】

首先观察如下界面
在这里插入图片描述
浏览器查看返回的state信息
http://localhost:8081/tags/71/model
查看tbl_basic_tag完成对应71为id对应的name

在这里插入图片描述
注意:
Modelpo是用来操作数据库的
Modeldto是用来和前段交互的
这样区分是用来隐藏数据库表结构
防止黑客进行数据库攻击
而ModelRepo是dao用来把po保存到数据库的

11.1 编写Controller控制层代码

//http://localhost:8081/tags/71/model
//1-使用tagService更新状态
//2-返回HttpResult

    @PostMapping("tags/{id}/model")public HttpResult changeModelState(@PathVariable Long id, @RequestBody ModelDto modelDto){service.updateModelState(id, modelDto.getState());return new HttpResult(Codes.SUCCESS, "执行成功", null);}

11.2 编写Service服务层代码

//首先根据modelRepo使用id查找对应的信息
//启动任务
//调用engine类中的封装好的方法启动任务
//modelPo调用setName
//停止任务
//调用engine类中的封装好的方法停止任务
//modelPo更新状态,传过来是几修改为几,modelRepo保存oozie的在有关四级标签配置modelPo状态

    @Overridepublic void updateModelState(Long id, Integer state) {ModelPo modelPo = modelRepo.findByTagId(id);if (state == ModelPo.STATE_ENABLE) {//启动流程engine.startModel(convert(modelPo));
//modelPo调用setNamemodelPo.setName(jobid);}if (state == ModelPo.STATE_DISABLE) {//关闭流程engine.stopModel(convert(modelPo));}//更新状态信息modelPo.setState(state);modelRepo.save(modelPo);}

11.3 编写引擎Service层代码

//1-new OozieParam的基本配置
//2-使用OozieUtils根据参数生成配置文件Properties对象
//3-通过标签Id(model)上传配置到HDFS(如coordinator.xml/workflow.xml)
//4-保留一份Properties方便后续如果出错可以查看
//5-运行任务
//6-返回JobId

@Overridepublic void startModel(ModelDto model) {// 设置动态的参数, 例如如何调度, 主类名, jar 的位置OozieParam param = new OozieParam(model.getId(),model.getMainClass(),model.getPath(),model.getArgs(),ModelDto.Schedule.formatTime(model.getSchedule().getStartTime()),ModelDto.Schedule.formatTime(model.getSchedule().getEndTime()));// 生成配置Properties properties = OozieUtils.genProperties(param);// 上传各种配置, workflow.xml, coordinator.xmlOozieUtils.uploadConfig(model.getId());// 因为如果不保留一份 job.properties 的文件, 无法调试错误OozieUtils.store(model.getId(), properties);// 运行 Oozie 任务OozieUtils.start(properties);}@Overridepublic void stopModel(ModelDto model) {}

11.4 测试

根据数据库查看状态信息:
 model_main应该从oozie的properties配置中获取

注意:这里根据自己服务器标签可以自主选择,这里选择#蘑菇街女装#消费偏好,对应的tbl_model的tag_id=95
在这里插入图片描述
查看任务状态

oozie job -oozie http://bd001:11000/oozie -info 0000007-191209104842815-oozie-root-C

注意:任务id从控制台或者数据库查看
在这里插入图片描述
在这里插入图片描述
停止后可以在重启,观察数据库表变化
在这里插入图片描述
在这里插入图片描述
从而完成Oozie和SpringBoot整合。
总结:

  1. Oozie支持基于Hadoop的任务调度,稳定成熟,无缝集成Hadoop
  2. Oozie支持任务状态的监控和持久化保存,支持失败流程控制
  3. Oozie支持命令行调度,还支持Rest-API调用

当然Oozie也有一些缺点:界面丑陋,xml文件编写复杂,功能太多,有的用不上较冗余,

注意:Oozie整合Spark的jar有的需要重新编译


http://chatgpt.dhexx.cn/article/90QoNYZu.shtml

相关文章

Oozie简介

在Hadoop中执行的任务有时候需要把多个Map/Reduce作业连接到一起&#xff0c;这样才能够达到目的。[1]在Hadoop生态圈中&#xff0c;有一种相对比较新的组件叫做Oozie[2]&#xff0c;它让我们可以把多个Map/Reduce作业组合到一个逻辑工作单元中&#xff0c;从而完成更大型的任务…

Oozie

文章目录 **一、** **Apache Oozie****1&#xff0e;** **Oozie概述****2&#xff0e;** **Oozie的架构****3&#xff0e;** **Oozie**基本原理**3.1&#xff0e;** **流程节点** **4&#xff0e;** **Oozie工作流类型****4.1&#xff0e;** **Work**Flow**4.2&#xff0e;** *…

工作流调度工具--Oozie

一、背景 一个完整的数据分析系统通常是由大量的任务单元组成&#xff0c;Shell脚本、Java程序、MapReduce程序、Hive脚本等等&#xff0c;各个任务单元之间存在时间先后及前后依赖关系。 为了很好的组织这样的复杂执行计划&#xff0c;需要一个工作流调度系统来调用执行。 简…

Oozie基础入门

前言&#xff1a; 因为工作需要用到oozie&#xff0c;但是网上的资料越看越迷茫&#xff0c;经过很大的努力&#xff0c;终于折腾清楚了&#xff0c;这里&#xff0c;做一个总结&#xff0c;帮助后来者更好地进行入门&#xff0c;当然&#xff0c;粗鄙之言&#xff0c;难免疏漏…

大数据调度工具oozie详细介绍

背景&#xff1a; 之前项目中的sqoop等离线数据迁移job都是利用shell脚本通过crontab进行定时执行&#xff0c;这样实现的话比较简单&#xff0c;但是随着多个job复杂度的提升&#xff0c;无论是协调工作还是任务监控都变得麻烦&#xff0c;我们选择使用oozie来对工作流进行调…

oozie详解

1、什么是Oozie Oozie是一种java web应用程序&#xff0c;它运行在java servlet容器中&#xff0c;并使用数据库来存储一下内容&#xff1a; ①工作流定义 ②当前运行的工作流实例&#xff0c;包括实例的状态和变量 Oozie工作流失放置在控制依赖DAG(有向无环图)中的一组动作&am…

大数据Hadoop之——任务调度器Oozie(Oozie环境部署)

文章目录 一、概述二、Oozie架构三、Oozie环境部署&#xff08;Oozie与CDH集成&#xff09;1&#xff09;添加服务2&#xff09;将 Oozie 服务添加到 CDH3&#xff09;自定义角色分配4&#xff09;数据库设置5&#xff09;审核更改6&#xff09;开始自动安装并自启 四、CDH的 H…

Java并发编程(一):多线程与并发原理回顾

今天来聊一聊经典的Java技术&#xff0c;并发编程。并发是程序的灵魂&#xff0c;一个优秀的Java程序一定会支持高并发&#xff0c;并且&#xff0c;并发编程也是面试环节中经常会问到的一个问题&#xff0c;那么今天我们以一道经典的Java面试题回顾一下Java的并发编程。废话不…

java并发编程的艺术和并发编程这一篇就够了

java并发编程的艺术(精华提炼) 通常我们在使用编发编程时,主要目的是为了程序能够更快的处理,但是并不是说更多的线程就一定能够让程序变得足够快,有时候太多的线程反而消耗了更多的资源,反而让程序执行得更缓慢 一.CPU的上下文切换 就算是单核CPU是能够处理多线程任务的,它只…

JAVA并发编程总结

一、基础知识 1.1 线程安全 当多个线程访问某个类时&#xff0c;这个类始终都能表现出正确的行为&#xff0c;那么就称这个类是线程安全的。 CAP理论 原子性 我们把一个或者多个操作在CPU执行的过程中不被中断的特性称为原子性. 可见性 当一个线程修改了对象状态后&#xf…

Java并发:整理自《Java并发编程实战》和《Java并发编程的艺术》

声明&#xff1a;Java并发的内容是自己阅读《Java并发编程实战》和《Java并发编程的艺术》整理来的。 图文并茂请戳 思维导图下载请戳 目录 (1)基础概念 (2)线程 (3)锁 (4)同步器 (5)并发容器和框架 (6)Java并发工具类 (7)原子操作类 (8)Executor框架(执行机制) (9)…

Java并发编程的艺术-并发编程基础

Java从诞生开始就明智地选择了内置对多线程的支持&#xff0c;这使得Java语言相比同一时期的其他语言具有明显的优势。线程作为操作系统调度的最小单元&#xff0c;多个线程能够同时执行&#xff0c;这将显著提升程序性能&#xff0c;在多核环境中表现得更加明显。但是&#xf…

java并发编程(下篇)

java里的阻塞队列 ArrayBlockingQueue 数组结构组成的有界阻塞队列 LinkedBlockingQeque 链表结构的无界阻塞队列 PriorityBlockingQueue 支持优先级排序的无界阻塞队列 DelayQueue 使用优先级队列实现的无界阻塞队列 LinkedBlockingDeque 链表结构组成的双向队列 并发工具…

Java并发编程之美——第一章 Java并发编程基础

文章目录 Time 2021-12-26——Hireek什么是线程线程的等待和通知等待线程终止的join方法让线程睡眠的sleep方法让出CPU执行权的yield方法线程中断demo 线程上下文切换线程死锁什么是死锁如何避免死锁 用户线程与守护线程ThreadLocalintroduction&#xff0c;下文只阐述重要的se…

Java并发编程入门这一篇就够了(文章很长,但很好哦)

Java并发编程入门这一篇就够了 一、进程与线程1. 进程2. 线程3. 二者对比 二、并行与并发三、Java线程1. 创建和运行线程2. 线程运行原理3. 常见方法4. 常用方法详解及异同区分5. 两阶段终止模式&#xff08;使得线程优雅的退出&#xff09;6.主线程与守护线程7. 线程五种状态8…

Java并发编程之Java线程

文章目录 前言01、线程简介02、线程池03、线程间通信总结 前言 记录一下Java并发编程的知识点。有部分内容是借鉴《Java并发编程的艺术》这本书的。本次先介绍一下线程。 01、线程简介 进程和线程的区别 进程&#xff1a;当一个程序被运行&#xff0c;即把程序的代码从磁盘加载…

Java并发编程的艺术

1、并发编程的挑战 1、上下文切换 CPU通过给每个线程分配CPU时间片来实现多线程机制。时间片是CPU分配给各个线程的时间&#xff0c;这个时间非常短&#xff0c;一般是几十毫秒。 CPU通过时间片分配算法来循环执行任务&#xff0c;当前任务执行一个时间片后会切换到下一个任务…

Java并发编程简介

并发编程简介 1. 什么是并发编程 所谓并发编程是指在一台处理器上“同时”处理多个任务。并发是在在同一实体上的多个事件。多个事件在同一时间间隔发生。 并发编程 ①从程序设计的角度来讲&#xff0c;是希望通过某些机制让计算机可以在一个时间段内&#xff0c;执行多个任务…

【java】Java并发编程系列-基础知识(非常详细哦)

文章目录 一、Java并发编程基础1.1 并发编程基本概念1.1.1原⼦性1.1.2 可⻅性1.1.3 有序性 二、内存模型三、重排序四、内存屏障五、总结 一、Java并发编程基础 主要讲解Java的并发编程的基础知识&#xff0c;包括原⼦性、可⻅性、有序性&#xff0c;以及内存模型JMM&#xff…

理解Java并发编程

计算机基础 要想理解Java多线程&#xff0c;一定离不开计算机组成原理和操作系统&#xff0c;因为&#xff0c;java的多线程是JVM虚拟机调用操作系统的线程来实现的 /*Thread.start() 方法中调用了原生的start0()方法 */ public synchronized void start() {if (threadStatus…