ImageVerifierCode 换一换
格式:DOCX , 页数:11 ,大小:24.74KB ,
资源ID:8024813      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/8024813.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(mapreduce的中间排序及jobtracker源码分析.docx)为本站会员(b****5)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

mapreduce的中间排序及jobtracker源码分析.docx

1、mapreduce的中间排序及jobtracker源码分析Map完成之后的中间过程:如果对hadoop的shuffle机制有所了解的人都知道,map所产生的中间数据在送给reduce进行处理之前是要经过排序的。具体的过程实际上是快速排序,堆排序和归并排序的完美结合。首先,当map函数处理完输入数据之后,会将中间数据存在本机的一个或者几个文件当中,并且针对这些文件内部的记录进行一次快速排序,这里的排序是升序排序。这段代码是在MapTask的内部类MapOutputBuffer中实现的。当map阶段完成后,系统会启动reduce过程。reduce过程会把这些由map输出的中间文件拷贝到本地,然后生

2、成一个或者几个Segment类的实例,以下我们称这些实例为segment。Segment类封装了这些中间数据,并且提供了一些针对这些中间数据的操作,比如读取记录等。在reduce端,这些中间数据可以存在内存中,也可以存在硬盘中。同时,系统还会启动两个merge(归并)线程,一个是针对内存中的segment进行归并,一个是针对硬盘中的segment进行归并。merge过程实际上就是调用了Merge类的merge方法。 Merge类的merge方法生成了一个MergeQueue类的实例,并且调用了该类的merge方法。MergeQueue类是PriorityQueue类的一个子类,同时实现了Raw

3、KeyValueIterator接口。PriorityQueue类实际上是一个小根堆,而MergeQueue的merge方法实际上就是将segment对象存储进父类的数据结构中,并且建立一个小根堆的过程。因此,hadoop的归并和排序不是两个分开的过程,而是一个过程。在将segment归并的同时进行了排序。Mapreduce的过程代码分析:mapreduce中几个主要的概念 mapreduce整体上可以分为这么几条执行的线索,jobclient,JobTracker与TaskTracker。JobClient 每一个job都会在客户端通过JobClient类将应用程序以及配置参数打包成jar文

4、件存储在HDFS,然后向JobTracker提交作业,JobTracker创建Task(即MapTask和ReduceTask)并将它们分发到各个TaskTracker服务中去执行。JobTracker JobTracker是一个master服务,hadoop服务端启动之后JobTracker接收job,负责调度job的每一个子任务task运行于TaskTracker上,并监控它们,如果发现有失败的task就重新运行它。一般情况应该把JobTracker部署在单独的机器上。TaskTracker TaskTracker是运行于多个节点上的slaver服务。TaskTracker主动与JobTr

5、acker通信,接收作业,并负责直接执行每一个任务。下图简单的描述了三者之间的关系:(上传不了图片,抱歉!)数据结构2.1 JobInProgressJobClient提交job后,JobTracker会创建一个JobInProgress来跟踪和调度这个job,并把它添加到job队列里。JobInProgress会根据提交的job jar中定义的输入数据集(已分解成FileSplit)创建对应的一批TaskInProgress用于监控和调度MapTask,同时在创建指定数目的TaskInProgress用于监控和调度ReduceTask,缺省为1个ReduceTask。2.2 TaskInPr

6、ogressJobTracker启动任务时通过每一个TaskInProgress来launchTask,这时会把Task对象(即MapTask和ReduceTask)序列化写入相应的TaskTracker服务中,TaskTracker收到后会创建对应的TaskInProgress(此TaskInProgress实现非JobTracker中使用的TaskInProgress,作用类似)用于监控和调度该Task。启动具体的Task进程是通过TaskInProgress管理的TaskRunner对象来运行的。TaskRunner会自动装载job jar,并设置好环境变量后启动一个独立的java ch

7、ild进程来执行Task,即MapTask或者ReduceTask,但它们不一定运行在同一个TaskTracker中。2.3 MapTask和ReduceTask一个完整的job会自动依次执行Mapper、Combiner(在JobConf指定了Combiner时执行)和Reducer,其中Mapper和Combiner是由MapTask调用执行,Reducer则由ReduceTask调用,Combiner实际也是Reducer接口类的实现。Mapper会根据job jar中定义的输入数据集按对读入,处理完成生成临时的对,如果定义了Combiner,MapTask会在Mapper完成调用该Co

8、mbiner将相同key的值做合并处理,以减少输出结果集。MapTask的任务全完成即交给ReduceTask进程调用Reducer处理,生成最终结果对。2.3 MapTask和ReduceTask一个完整的job会自动依次执行Mapper、Combiner(在JobConf指定了Combiner时执行)和Reducer,其中Mapper和Combiner是由MapTask调用执行,Reducer则由ReduceTask调用,Combiner实际也是Reducer接口类的实现。Mapper会根据job jar中定义的输入数据集按对读入,处理完成生成临时的对,如果定义了Combiner,MapT

9、ask会在Mapper完成调用该Combiner将相同key的值做合并处理,以减少输出结果集。MapTask的任务全完成即交给ReduceTask进程调用Reducer处理,生成最终结果对。整体流程一道MapRedcue作业是通过JobClient.rubJob(job)向master节点的JobTracker提交的, JobTracker接到JobClient的请求后把其加入作业队列中。JobTracker一直在等待JobClient通过RPC提交作业,而TaskTracker一直通过RPC向 JobTracker发送心跳heartbeat询问有没有任务可做,如果有,让其派发任务给它执行。如

10、果JobTracker的作业队列不为空, 则TaskTracker发送的心跳将会获得JobTracker给它派发的任务。这是一道pull过程。slave节点的TaskTracker接到任务后在其本地发起Task,执行任务。以下是简略示意图:Jobclient在编写MapReduce程序时通常是上是这样写的:Configuration conf = new Configuration(); / 读取hadoop配置Job job = new Job(conf, 作业名称); / 实例化一道作业job.setMapperClass(Mapper类型);job.setCombinerClass(Co

11、mbiner类型);job.setReducerClass(Reducer类型);job.setOutputKeyClass(输出Key的类型);job.setOutputValueClass(输出Value的类型);FileInputFormat.addInputPath(job, new Path(输入hdfs路径);FileOutputFormat.setOutputPath(job, new Path(输出hdfs路径);/ 其它初始化配置JobClient.runJob(job);4.1 配置JobJobConf是用户描述一个job的接口。下面的信息是MapReduce过程中一些较关

12、键的定制信息:/4.2 JobClient.runJob():运行Job并分解输入数据集4.2 JobClient.runJob():运行Job并分解输入数据集runJob()提交作业,如何等待返回的状态,根据状态返回不同的结构给客户端。其中runJob()使用submitJob(job)方法向 master提交作业。submitJob(Job)方法的流程一个MapReduce的Job会通过JobClient类根据用户在JobConf类中定义的InputFormat实现类来将输入的数据集分解成一批小的数据集,每一个小数据集会对应创建一个MapTask来处理。JobClient会使用缺省的Fil

13、eInputFormat类调用FileInputFormat.getSplits()方法生成小数据集,如果判断数据文件是isSplitable()的话,会将大的文件分解成小的FileSplit,当然只是记录文件在HDFS里的路径及偏移量和Split大小。这些信息会统一打包到jobFile的jar中。hadoop分布系统文件系统hdfs依次上传三个文件: job.jar, job.split和job.xml。 job.xml: 作业配置,例如Mapper, Combiner, Reducer的类型,输入输出格式的类型等。 job.jar: jar包,里面包含了执行此任务需要的各种类,比如 Map

14、per,Reducer等实现。 job.split: 文件分块的相关信息,比如有数据分多少个块,块的大小(默认64m)等。 (这些信息如何得到?)这三个文件在hdfs上的路径由hadoop-default.xml文件中的mapreduce系统路径mapred.system.dir属性 + jobid决定。mapred.system.dir属性默认是/tmp/hadoop-user_name/mapred/system。写完这三个文 件之后, 此方法会通过RPC调用master节点上的JobTracker.submitJob(job)方法,等待返回状态,此时作业已经提交完成。接下来转到JobTr

15、acker上执行。4.3 提交JobjobFile的提交过程是通过RPC(远程进程调用)模块来实现的。大致过程是,JobClient类中通过RPC实现的Proxy接口调用JobTracker的submitJob()方法,而JobTracker必须实现JobSubmissionProtocol接口。JobTracker创建job成功后会给JobClient传回一个JobStatus对象用于记录job的状态信息,如执行时间、Map和Reduce任务完成的比例等。JobClient会根据这个JobStatus对象创建一个NetworkedJob的RunningJob对象,用于定时从JobTracke

16、r获得执行过程的统计数据来监控并打印到用户的控制台。与创建Job过程相关的类和方法如下图所示JobTracker5.1 JobTracker启动(bin/start-all.sh后就启动了jobtaracker和下列进程)JobTracker类中有一个main()函数,在软件启动的时候执行此main()函数启动JobTracker进程,main()中生成一个JobTracker的对象,然后通过tracker.offerService()语句启动服务,即启动一些线程,下面是几个主要的线程:taskScheduler:一个抽象类,被JobTracker用于安排执行在TaskTrackers上的ta

17、sk任务,它使用一个或多个JobInProgressListeners接收jobs的通知。另外一个任务是调用JobInProgress.initTask()为job初始化tasks。启动,提交作业,设置配置参数,终止等方法。completedJobsStoreThread对应completedJobStatusStore;CompletedJobStatusStore类:把JobInProgress中的job信息存储到DFS中;提供一些读取状态信息的方法;是一个守护进程,用于删除DFS中的保存时间超过规定时间的job status删除,interTrackerServer,抽象类Server类

18、型的实例。一个IPC (Inter-Process Communication,进程间通信)服务器,IPC调用一个以一个参数的形式调用Writable,然后返回一个Writable作为返回值,在某个端口上运行。提供了call,listener,responder,connection,handle类。包括start(),stop(),join(),getListenerAddress(),call()等方法。这些线程启动之后,便可开始工作了。job是统一由JobTracker来调度的,把具体的Task分发给各个TaskTracker节点来执行。下面来详细解析执行过程,首先先从JobTracke

19、r收到JobClient的提交请求开始。5.2.1 JobTracker.submitJob() 收到请求当JobTracker接收到新的job请求(即submitJob()函数被调用)后,会创建一个JobInProgress对象并通过它来管理和调度任务。JobInProgress在创建的时候会初始化一系列与任务有关的参数,调用到FileSystem,把在JobClient端上传的所有任务文件下载到本地的文件系统中的临时目录里。这其中包括上传的*.jar文件包、记录配置信息的xml、记录分割信息的文件。5.2 JobTracker.JobInitThread 通知初始化线程JobTracker

20、 中的监听器类EagerTaskInitializationListener负责任务Task的初始化。JobTracker使用jobAdded(job)加入job到EagerTaskInitializationListener中一个专门管理需要初始化的队列里,即一个list成员变量jobInitQueue里。resortInitQueue方法根据作业的优先级排序。然后调用notifyAll()函数,会唤起一个用于初始化job的线程JobInitThread来处理?。JobInitThread收到信号后即取出最靠前的job,即优先级别最高的job,调用TaskTrackerManager的ini

21、tJob最终调用JobInProgress.initTasks()执行真正的初始化工作。5.3 JobInProgress.initTasks() 初始化TaskInProgress任务Task分两种: MapTask 和reduceTask,它们的管理对象都是TaskInProgress 。首先JobInProgress会创建Map的监控对象。在initTasks()函数里通过调用JobClient的readSplitFile()获得已分解的输入数据的RawSplit列表,然后根据这个列表创建对应数目的Map执行管理对象TaskInProgress。在这个过程中,还会记录该RawSplit块

22、对应的所有在HDFS里的blocks所在的DataNode节点的host,这个会在RawSplit创建时通过FileSplit的getLocations()函数获取,该函数会调用DistributedFileSystem的getFileCacheHints()获得。当然如果是存储在本地文件系统中,即使用LocalFileSystem时当然只有一个location即“localhost”了。创建这些TaskInProgress对象完毕后,initTasks()方法会通 过createCache()方法为这些TaskInProgress对象产生一个未执行任务的Map缓存nonRunningMapC

23、ache。slave端的 TaskTracker向master发送心跳时,就可以直接从这个cache中取任务去执行。其次JobInProgress会创建Reduce的监控对象,这个比较简单,根据JobConf里指定的Reduce数目创建,缺省只创建1个Reduce任务。监控和调度Reduce任务的是TaskInProgress类,不过构造方法有所不同,TaskInProgress会根据不同参数分别创建具体的MapTask或者ReduceTask。同样地,initTasks()也会通过createCache()方法产生nonRunningReduces成员。JobInProgress创建完Tas

24、kInProgress后,最后构造JobStatus并记录job正在执行中,然后再调用JobHistory.JobInfo.logStarted()记录job的执行日志。到这里JobTracker里初始化job的过程全部结束。5.3.2 JobTracker调度Jobhadoop默认的调度器是FIFO策略的JobQueueTaskScheduler,它有两个成员变量 jobQueueJobInProgressListener与上面说的eagerTaskInitializationListener。JobQueueJobInProgressListener是JobTracker的另一个监听器类,

25、它包含了一个映射,用来管理和调度所有的JobInProgress。jobAdded(job)同时会加入job到JobQueueJobInProgressListener中的映射。JobQueueTaskScheduler最重要的方法是assignTasks ,他实现了工作调度。具体实现:JobTracker 接到TaskTracker 的heartbeat() 调用后,首先会检查上一个心跳响应是否完成,是没要求启动或重启任务,如果一切正常,则会处理心跳。首先它会检查 TaskTracker 端还可以做多少个 map 和 reduce 任务,将要派发的任务数是否超出这个数,是否超出集群的任务平均

26、剩余可负载数。如果都没超出,则为此 TaskTracker 分配一个 MapTask 或 ReduceTask 。产生 Map 任务使用 JobInProgress 的 obtainNewMapTask() 方法,实质上最后调用了 JobInProgress 的 findNewMapTask() 访问 nonRunningMapCache 。上面讲解任务初始化时说过,createCache()方法会在网络拓扑结构上挂上需要执行的TaskInProgress。findNewMapTask()从近到远一层一层地寻找,首先是同一节点,然后在寻找同一机柜上的节点,接着寻找相同数据中心下的节点,直到找了

27、maxLevel层结束。这样的话,在JobTracker给TaskTracker派发任务的时候,可以迅速找到最近的TaskTracker,让它执行任务。最终生成一个Task类对象,该对象被封装在一个LanuchTaskAction 中,发回给TaskTracker,让它去执行任务。产生 Reduce 任务过程类似,使用 JobInProgress.obtainNewReduceTask() 方法,实质上最后调用了 JobInProgress 的 findNewReduceTask() 访问 nonRunningReduces。6. TaskTracker6.1 TaskTracker的启动与J

28、obTracker一样,里面包含一个main()方法,在hadoop启动的时候启动此进程。Main()方法最主要的一句话TaskTracker(conf).run();TaskTracker(conf)获取本机的一些配置信息,初始化服务器并启动服务器(StatusHttpServer);然后调用initialize(),这个方法才是真正构造TaskTracker的地方,把它作为一个单独的方法便可以再次调用并可以在close()之后回收对象,就是初始化一些变量对象,最后启动线程:taskMemoryManager为TaskMemoryManagerThread类的对象。管理本机上task运行时内

29、存的使用,杀死任何溢出和超出内存限制的task-trees。mapLauncher与reduceLauncher都是TaskLauncher类的对象,其作用是启动maptask和reducetask任务线程。根据tasksToLaunch判断是否需要新建任务,其中的调用的关系为:run()startNewTask()localizeJob()launchTaskForJoblaunchTask()localizeTask。run()方法中启动TaskTracker服务器然后一直循环。循环会尝试连接到的JobTracker。主要调用了两个方法startCleanupThreads(),offer

30、Service()。startCleanupThreads()启动为守护进程,可以用来删除一个独立线程的路径。offerService()类似于JobTracker中的offerService()方法,即服务器执行的主循环。规定的时间内给JobTracker发送心跳信息,并处理返回的命令。下面具体介绍流程中的每一步。6.2 TaskTracker加载Task到子进程Task的执行实际是由TaskTracker发起的,TaskTracker会定期与JobTracker进行一次通信,报告自己Task的执行状态,接收JobTracker的指令等。如果发现有自己需要执行的新任务也会在这时启动,即是在T

31、askTracker调用JobTracker的heartbeat()方法时进行,此调用底层是通过IPC层调用Proxy接口实现。6.2.1 TaskTracker.run() 连接JobTrackerTaskTracker的启动过程会初始化一系列参数和服务,然后尝试连接JobTracker(即必须实现InterTrackerProtocol接口),如果连接断开,则会循环尝试连接JobTracker,并重新初始化所有成员和参数。6.2.2 TaskTracker.offerService() 主循环如果连接JobTracker服务成功,TaskTracker就会调用offerService()函

32、数进入主执行循环中。这个循环会每隔10秒与JobTracker通讯一次,调用transmitHeartBeat(),获得HeartbeatResponse信息。然后调用HeartbeatResponse的getActions()函数获得JobTracker传过来的所有指令即一个TaskTrackerAction数组。再遍历这个数组,如果是一个新任务指令即LaunchTaskAction则调用调用addToTaskQueue加入到待执行队列,否则加入到tasksToCleanup队列,交给一个taskCleanupThread线程来处理,如执行KillJobAction或者KillTaskAction等。6.2.3 TaskTracker.transmitHeartBeat() 获取JobTracker指令在transmitHeartBeat()函数处理中,TaskTr

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1