2020.9.13(MapReduce原理,Yarn原理)

在某个领域比我牛的人,一定是我不擅长的领域。我擅长的领域,没有几个比我牛的。
今天把前面的知识稍微的讲一讲,主要是学教习方法。如果只是干讲知识的话,后面学习新的知识的时候,等于会重复造轮子,没有学习方法,更强调的是学习方法。随着学的东西越来越多,会有一个感觉,我学的这个东西和前面的东西好像。这时候如果能找到这个感觉的话,是件好事。因为技术是经常迭代更新的。
比如说从hdfs说起,它的模型-存储模型,主要描述它的特征:切块,块散列到及群里,为了分治,在讲hdfs分布式文件系统的时候还刻意强调一点,通过模型要关注这个东西这么去设计,这个分治它的目的->为了分布式计算
块的概念,副本全部说完之后,它的实现。模型怎么去实现的,学一个东西往往先去感知这个东西是做什么事情的,比如hbase,mangodb学这学那的。当感觉有了,马上看的就是架构框架。尤其在大数据这个圈里,关注这个架子,在框架里非常重要的一个东西,就是角色。
大数据里大部分东西都是分布式的,分布式就是有不同的角色在不同的地方,但是他们之间还有一些通信协作。所以当一个技术既知道他是干什么事的,又知道是怎么实现的,里面角色都分为哪些。做了什么事情,比如hdfs里面又namenode管理元数据的,有datanode存块的,他们两者之间还有一些关联关系,比如心跳,汇报。角色这块知道怎么实现了,还要关注一个细节。每一个技术自身有一些自己特长的地方/特点。这个东西支持未来架构师:技术选型。比如现在知道一个hdfs分布式文件系统了,留一个作业,去百度搜一下,还有没有其他的分布式文件系统,如果想使用分布式文件系统做一些事情,那么两个分布式文件系统应该选哪个来使用,这个时候就要找每个系统的特长特点了。架构师一般就是在做技术选型,因为他要解需求,一个需求有很多的点去实现,每个点上会有很多相同相类似的技术。在里面挑出一个最合适的才有意义。
hdfs分布式文件系统主要是存文件的,文件这个维度里面,读写流程就很重要的,尤其在讲到api的时候,读写流程api的一些实现可以拿到一些数据的原数据,拿到一些偏移量,可以拿到一些location,就恰恰是这些东西,可以完好的支持分布式计算。
这个技术只要按照这个思路走,模板教给你了。
上节课学的mapreduce:也尝试按照这个模板走一遍。
在文件系统叫存储模型,mapreduce叫计算模型:分布式计算框架有很多,现在刚学了一个mapreduce,这时候要先去关注模型。他是怎么去的,未来还要其他的分布式计算框架,他们的模型之间一定是有些关联关系,有些差异,或者有些扩展和升级的,比如说spark就是对mapreduce的扩展和升级,像flink就是另外一套计算模型,因为mapreduce是批量式计算,flink是流式计算。
怎么去聊计算模型的?
2个阶段:map阶段,reduce阶段,且这两个阶段是种线性阻塞的关系。map阶段完成之后reduce阶段才能计算。
map阶段是根据单条记录的加工和处理,reduce阶段是按组多条记录加工处理。这个时候有组的概念才会有kv的概念。
mapreduce叫做批量计算,map拿一批数据,每条记录都处理完之后,全都转成kv了,这时候所有数据都从一个状态转成另一个状态了。这时候reduce各自拉回自己的数据,这样会产生一个阻塞。或者线性依赖的关系,这样的一个计算特征叫做批量计算。未来如果接触流式计算,计算也是分很多的步骤和阶段的,但是阶段之间不是阻塞的,一定要找这种感觉 , 批量计算就是我有一批数据,这批数据无论是怎么计算,第一步得先达到一个状态,这个状态有了,只有他完成结束之后,这批数据去了这个reduce,这批数据去了另外一个reduce分组计算这是第二步,map阶段就阻塞了。
什么是流式计算的框架?还是有若干个步骤,这批数据可以是批量的,可以是实时产生过来的数据,数据过来的时候,两个节点之间并没有阻塞关系。有点像一个管道,大家都会排着队往里走,只不过会有很多的阶段完成相似的计算而已。
在聊计算模型的时候要有一个画像,把它描述的很合理。可以回顾一下图。
当模型这个层次完成之后,接下来开始模型是怎么去实现的。逻辑知识感觉都听懂了,一让去实现,写出这个程序又开始懵了。只有实现这个方式/框架架构,在听完了之后,才真正理解了描述的东西,从逻辑到物理的映射,必然关注的 也是角色。在map到reduce的过程当中,框架做了什么事情,你要做什么事情,有哪些角色帮你做了什么事,最终给你一种感觉就是框架抹杀了一些分布式的复杂度,你只需要关心核心业务就可以了。找到这种感觉。完全靠自主学习的方式。
比如理论知识完之后,我们开始聊MR计算框架:
注意:hadoop当中,mapreduce是计算框架,hdfs是存储框架,存储是分布式的,为了要支持计算,其实存储和计算是在同一个集群共生的,没有存储层,不知道计算什么拿不到数据。首先第一件事情,现在图中描述集群当中已经学完的角色,比如说有nameNode,还要一些从节点,比如说dataNode,我们的数据的块是被散列到dataNode里去的,而在hdfs当中,除了有nameNode,dataNode,还要很重要的客户端角色,客户端和namenode通信,和datanode通信,访问原数据,访问数据的块。这是计算框架一些角色的组成。当这个有了之后,思考我们聊的分布式计算模型当中有两个阶段,分别是map和reduce,如果现在听懂了,框架默认是一个map对应一个切片,一个切片对应一个块。而且也知道这个map一定会按照这个块移动过去。现在来想一想,当你开发的时候,写了一个map类,写了一个reduce类,写了这么两个计算的对象类,那么这两个东西是如何跑到数据那去的,计算向数据移动是如何实现的呢?
实现之后,假设计算向数据移动之后,是怎么计算的呢,这个流程,最普通的思维就是我把程序可以扔到datanode上,因为datanode会有block块的概念,关键是扔程序,你知道把程序扔到哪里么,怎么去扔啊?每个块有3个副本,那么这三台当中,哪台最合适去扔呢?namenode怎么知道这件事呢?这个过程当中的确会问namenode这个数据他的块有哪些,每个块在哪个datanode里,这是namenode可以给你说的,但是怎么扔过去,认为拷贝过去么,那么每次计算都要拷贝这么多复杂的事情么?
模型层聊完之后,它是如何实现的?
这个东西怎么移动起来的,谁把它弄过去的。弄过去的手段是什么手段是不是要分析清楚。有一句话,人是懒惰的,懒惰一定会促使科技的进步,如果有一套程序可以代替人完成计算的移动,人就可以很轻松的歇着了。把jar,scp过去还是需要人为的去操作,这些方式的确可以,写个脚本也可以完成这些事情,但这时候更希望的是有一套独立的东西,而且在移动的时候,那三个副本,他还得评判一下那个节点当中,这三个节点当中,哪个节点的资源剩余的更多,更更利于要移动过去。如果想把一个计算程序移动到合适的节点,这里面牵扯到两个概念:
一个叫做资源管理,一个叫做任务调度。
也就是说有一个资源他得知道这么多节点,哪个节点上面有多少的剩余内存,多少的核心,多大的网络,多大的磁盘,因为资源它得统一管理起来。
然后呢,还得有一个任务的调度,也就是说当有一个程序想变成分布式执行的时候,它要把这个程序分成多少个副本,应该在这么多节点当中移动到哪些资源节点剩余最多的地方最合适。
20分钟

框架的实现,有一个本质的目的目标/实现方向。就是计算向数据数据移动。那么首先hdfs肯定会暴露数据的位置。这是hdfs给我们提供的功能,那么剩下就是如何计算,如何去移动,这里面会牵扯到两个点,第1个点就是资源管理。是集群的整个的资源的管理。第二个就是任务调度。因为我们每次计算的程序不一样,每次这些块是在不同的节点当中去,所以它一定会有一个调度程序,按照每次你提交这个任务需要进行这个数据的一个分布,以及它掌管那个资源的情况来向合适节点去分发
然后就因为人是懒惰的,然后需要有一套东西出来要东西要代替人,然后人就感觉分布式这个城这个复杂度跟人没有关系,所以这里面就带出mapreduce框架当中要有一套东西。这套东西是什么?
首先它也是一个主从架构,要有一个jobTracker。就想成它是一个人,有一个人是负责管理的,也就是说每次你提交程序都是给他,他来代替人,然后选择合适的datanode。当然,这时候注意了,计算向数据移动过去之后是一些j vm,这个jvm如何在另外一个点启动的呢?然后以及它占有多少资源,怎么去管理这些任务呢?它失败没失败呢?创建销毁和拉取这些计算程序的过程当中,

其实在mapreduce框架当中它有另外一套角色,叫做taskTracker,注意这两个是一类的,因为计算要向数据移动,所以你的计算的这些个角色一定要和你的存储的这些从角色,必须是1:1的关系,也就是说数据在上传的时候,数据会散列进去走这个白色字体的流程。
计算的时候,除了jobTracker和taskTracker也会有计算的客户端,也就是我想计算啥。 学完hdfs再理解mapreduce框架,就好理解了,这边是数据在这,数据要分过去散开,这边的计算程序,计算程序要扔出去要散开,只不过这个计算程序扔的时候要比数据端复杂一些,因为这个计算程序是依赖这些数据,因为他不可能计算所有数据,他只关心他自己的一批数据,那批数据有可能存在不同的节点,另外一批数据可能散在另外一批节点,他们可能有重叠,但是这个事情都是要由这边的框架来解决的。
这个框架这个角色应该怎么去划分大概的能得出一个结论,但是信息度还不够,然后这里面可能有我们的taskTracker和jobTracker,jobTracker它里边应该具备的能力分别是资源管理和任务调度
taskTracker,根据我们刚才描述比如,这个物理机当中为什么有一个namenode,还要有一个taskTracker?
因为namenode是管理块的,taskTracker是管理未来这里面启动的一些JVM进程管理那些任务的。
jobTracker都有任务的调度了,从mapTask和reduceTask中调出去了,那么那边是要管理被调度过去那些task的启动、监控之类的。
所以taskTracker负责任务的管理。
上面说了,jobTracker可以知道集群当中所有资源的情况,那么job Tracker是怎么知道每个节点资源情况的呢?其实是TaskTracker做心跳汇报的。每一个taskTracker都要向jobTracker去说这边剩余多大内存,剩余多少个槽位,还能启动几个任务
所以taskTracker还有资源汇报。这个资源是要汇报给我们jobTracker的,他是主,他是从。
还有一个角色就是客户端。
客户端会做哪些事情呢?很重要
我们为什么推导出分布式情况下,一般我们都会用主从架构?
推导过程:因为主从架构中,主是单点的,他无论做什么事情自己说一就是一,说二就是而。非常好管理的人,如果没有主,那么剩下就是很难的框架了,这个框架当中所有的taskTracker,他们没有一个领导的话, 那么他们都要互相交换数据,每个人都要知道整个集群所有的资源情况,那么这个客户端想连谁就连谁了,因为这里面没有主了嘛,谁都可以大家做主,所有人都想当家作主的前置条件就是每个人都要责任心,每个人都要知道每天这个家里应该干哪些家务,知道家里还剩多少油数多少盐。但是如果家里有父母,你会变得很轻松。所以一般主从模型是集群非常推崇的一种集群模式。
那么在宏观粗略层面上,我们知道了有这些角色,我们的实现就可以实现了。
但是这里面其实好像说完之后胡扯了一顿没有解决计算数据移动这个整体的细节对不对?
这里面其实最重要的角色恰恰就是客户端,以前你可能对客户端不怎么感冒,觉得客户端不就是很小的一个东西嘛,那么今天听了mapreduce之后,希望你对客户端有一个重新的认识。
客户端,其实是很重要的,那么这里面我们来聊一下客户端是怎么去推动计算向数据移动这个实现的

首先我们要明白学习的mapreduce叫做分布式计算程序。未来会开发一个程序,这个程序是一个jar包,jar包是可以启动的。把jar包启动的时候就是启动在了一个客户端程序里。
jar包以及里面写的一些类,就是在客户端程序里。客户端里的jar包会做哪些事情呢?
这个jar包有什么用?jar包里面会包含什么东西?jar包就是我们写的逻辑,这个逻辑里边就分为两个阶段:我们的map和我们的reduce都在这个jar包,那些类都在这个jar包里。
我们的代码逻辑是在这里边,这就是个程序,但是我们是不是要将计算向数据移动?
数据在这边是怎么移动过去的,客户端很重要。客户端里面做了如下的事情:
首先计算程序肯定是要计算数据?
那么计算数据数据是归谁管的?是归我们hdfs这边管的。
客户端第1件非常重要的一件事情:会根据每次的计算数据,咨询我们的namenode,这批数据有多少个块。这些块都在哪,以及我这个计算框架如果想跑这个程序,人为有没有干预?如果没有干预的话,它那层解耦的切片默认等于块。
客户端启动,你告诉了这个客户端,说这次我要计算a目录的10个文件,客户端就会去访问namenode,取回a目录的10个文件的所有的元数据,就是咨询nemenode元数据。
要元数据的目的是什么?
原数据里边会包含block块的相关信息
他拿那个元数据要计算切片。
客户端做很多事情,但是这点是最重要的!!!
客户端会根据每次计算的数据,咨询namenode元数据获得一些块,根据那个块,计算自己的切片,
因为切片在框架中默认是等于我们这个块大小的,所以这10个你有多少块就会有多少个切片。
然后我又说了切片是解耦,你可以根据cpu密集型或io密集型,调整切片的大小如果一个切片是块1/2,你有10个块,那么就会有什么20个切片,不管怎么样,计算切片最终得到一个切片的清单
切片的清单,就是我这次计算的这批数据,一共切了多少个切片,只要切片清单一算出来,客户端算出来,你可以得到如下的东西:
一个切片对应一个map,map的数量就有了。
客户端现在还没有发生计算。客户端只是根据要计算哪个数据,他拿着数据咨询元数据,它就可以得到一个切片清单,有了切片清单第1个可以得到就是map数量有多少。
我这个作业这次要计算,我有多少个map,是并行的并行度是多少?
那么未来如果要申请这个移动位置的话,应该移动到多少个地方?应该消耗多少资源?这事通过他就可以就可以明白了。
而且这时候在开始跟你讲的时候,讲那个模型的时候也说过,切片是逻辑的,block是物理的。block身上有offset(每个block块上都有偏移量),然后split和block是有映射关系。
最简单的关系就是框架默认的关系,即一个切片等于一个block块。所以block块的偏移量也是切片的偏移量。
block块除了有偏移量(offset)还有locations(每一个块他的副本都在哪些机器上)
结果:split包含偏移量,以及split对应的map任务应该移动到哪些节点(locations当中获得位置)
以上解释了这个客户端在还没有发生计算之前,他为什么要得到一个清单这个事清单?这个清单里面包含什么东西了?
我给你举个例子,比如这个清单当中有一个split01切片,这个切片可能是A文件的,从A文件的0号开始读起,要读500个字节,这个切片对应的是第1个块,那个块的三个位置分别是node1和node3和node5这三个节点可以去。
什么样的清单,就是很多这样的一些数据。
当这个清单有了之后,我把这个清单交到你的手里,你拿这个清单都可以做一件事情,手工都用scp把我们的jar包
比如第1个切片对的那个map程序,可以选择node1,第二个切片的程序可以选择node3,挑一个节点就可以移动了。
所以只要拿到切片清单,就在完成一件事情,理论上是可以支持计算向数据移动了。
所以为什么说客户端很重要?
没有客户端这一步,谁都不知道,这个程序,应该移动到哪里去!!
那么这一块你能理解之后,但是你要发现一个小问题是,不是每一个切片都有n个位置可以去,所以这时候你要有理解的一个层次,就是客户端也仅是给出了一个移动的可能的范围,也就是这个切片对应的map可以移动到这三个node节点,但是应该去到哪里呢客户端并不知道。
客户端不能拍板说我第1个切片去node1就可以了,因为整个集群有很多机器,你的客户端没有和任何节点有过任何连接和心跳,他并不知道每个节点到底是多少核的CPU,多大的内存,那么这里面只有谁知道?
只有jobTracker知道!!
只有jobTracker才和节点之间有心跳,taskTracker汇报子节点的状态和资源,
先知道未来肯定是要有jobTracker,也要用到切片清单,但先把它放一放。
客户端除了要生成切片清单,第2件最重要的事情:
客户端还会生成计算程序,未来运行时的相关配置文件(.xml配置文件),现在做变成要有一种感觉,我的任何程序,现在有框架有什么之类的,都会有相关的配置文件,或者相应的配置方法,或者properties,就是在一种个性化运行。
我们分布式计算程序,未来计算起来之后,内存要开多大呢?堆是多大的?序列化反序列化的类是什么类?有很多的东西可以配,这就根据每次计算的东西不一样,来调整的(性能调优)。
所以程序肯定是需要配置文件的,这也是客户端在还没有计算之前,相应的东西都要产生。
现在有一个清单文件,有一个配置文件。
第三件重要的事情,客户端是一个单点,是在某一台计算机起的一个客户端,那么这里面的像jar包里面这些类,以及我们的一个切片的数据,清单以及我们的配置清单,其实都是未来这个计算程序移动过去之后,可能会用到的东西,那么这个时候如果计算向数据移动的话,移动这个动词,是说由客户端把它们拷过去或者由jobTracker把它拷过去了吗?
那么这里面你会想到一个问题,jobTracker肯定是单点的,然后他可能发着发着他就挂了,
所以计算向数据移动,移动这个词到底是什么语义?怎么叫做移动了?
未来的移动应该相对可靠。
那么在学过的知识当中什么东西是相对可靠的?这些文件,这些数据未来可以相对可靠的被更多的节点去访问和知道?hdfs
所以第3步:
客户端会将我们的jar包,split清单,配置xml文件上传到hdfs的目录中。
这就是所谓的计算向数据移动当中,移动,其实是由客户端先把这些东西上传到hdfs。未来哪些节点,想去计算,分配到计算任务了,其实用那个节点的taskTracker,从hdfs中把数据下载回来。
从客户端到taskTracker借用hdfs这个握手的过程其实就是在做计算向数据移动的过程!!!
这也是由客户端支撑的。这些事情是在计算发生前,由客户端先去为未来的这个分布计算做的一个前期的一个准备工作。

那么其实你聊了这么多之后啊,仅仅也是一个准备而已。因为说了客户端不会和所有人去建立连接,他不知道这样的情况,所以最终是客户端最终还是要调用jobTracker

所以第4步:
客户端会调用jobTracker,通知要启动一个计算程序了,并且告知文件都放在了hdfs的哪些地方。

一定要明白hdfs是一个系统,它里边由namenode和datanode组成,没有直管元数据,这个过程是我们这边的客户端里边包含了hdfs的api,他会把jar包,本地生成的切片文件配置文件,然后等于调用了hdfs的api,然后访问了namenode,namenode给他返回了一些datanode,最终它是把这些数据变成块写到了datanode里面,就是也散到集群里边去了。

在上传到hdfs的目录中还一个小知识点,上传的数据,副本数是10个。框架上默认的副本的数量是三个,为什么客户端上传的副本数是10个?

因为未来map的并行度可能是几十几百,代表未来会有很多的taskTracker去找datanode下载相应的jar包,相当于配置文件。假设只有3个副本只有3个datanode有的话,有50个taskTracker在50个节点去拉取数据的话,会在这三个节点的网卡IO上产生瓶颈。但是你副本数变大,会支持更多的分散的拉取,有负载的好处。
在未来就把hdfs当做一个文件系统来用。

如果你文件上传的这个东西很大的话,它也是会切割的,但计算程序和配置文件可能连一兆都没有,都是可以配置的,
客户端上传的东西,基本上不会被切割的,任务执行完之后这些东西肯定是会被删除,不会删除的话,在企业当中工作每天跑这种程序,一天要跑大一两千个,那么就是会有一两千次这样的一个提交,你jar包再小一年下来的话,它损耗空间也是很多的
这些配置是可以在他的api里去添加,也可以写文件作为参数传进去,或者加载配置文件,这个几种方式都可以。
客户端的逻辑规划结束之后,
jobTracker收到启动程序之后要做哪些事情?
1.从hdfs中取回split清单(客户端时逻辑规划,只有它才会做一些决策的事情)
2.根据自己收到的taskTracker汇报的资源,最终确定每一个split对应的map应该去到哪一个节点(会生成一千二确定的清单这个清单当中就描述了,每一个map应该去到哪一个节点。)
那么清单有了之后,那么这时候注意了,你jobTracker已经定义好了,第1个map应该去node1,node3,所有的map都定义好之后,注意有两个方向,一个是由jobTracker去通知TaskTracker说你应该去跑一个map了,还有一个方向,是由taskTracker在心跳的时候(每3秒一次),您刚才在客户端提交程序当中有没有在我这分配一个任务?
有这么两种方向。目前来说jobTracker使用的是后者。
3.未来taskTracker在心跳的时候会从jobTracker取回分配到自己的任务信息。
当他取了信息之后,jobTracker这个环节就结束了。那么下面就是我们的TaskTracker。
TaskTracker:
1.taskTracker在心跳取回了任务后,任务信息就是切片的信息,这个切片信息当中还有我们job提交的相关的所有东西,他要做一件事情,你这个job的计算程序代码在哪?
代码已经被上传到hdfs当中去了,所以这时候第1件事情先从我们的jobTracker上取回任务,就是这个切片的描述信息。
第2点是要从hdfs中下载jar包,xml配置文件等一系列资源会下载好到本机,那么这时候本机环境当中有jar包,jar包当中有类了。
第3件事情才是最终启动任务描述中的mapTask或reduceTask,关键是心跳取回的是哪一种类型的。
但是这两个类型的任务的逻辑代码都在jar包里,我们把所有代码都写在一个jar包里了,到这步的时候,最终这一过程,最终代码在某一个节点被启动是通过客户端上传,TaskTracker下载来实现的。
这一过程叫做计算向数据移动的实现。

之前说的一些逻辑的东西,就是靠着这些角色之间,你来调我来调你,互相调用,客户端要为jobTracker准备什么,jobTracker要拿到什么东西,要做什么事情,然后最终taskTracker再去拉取什么东西,最终就把这程序跑起来了,大体是这么一个流程。

这个笔记已经写的比较完整了。
那么这个事能聊明白之后啊,我们再稍微的加一点复杂度,这时候有一个客户端这样跑了出来,这时候你和你的同事两个人都想提交程序,

最终会一个后果,这两个人都会上传东西,最终这两个人都会去调用jobTracker,然后这时候jobTracker要为这两个程序都要去做资源的统计,以及向taskTracker划分这个任务,最终TaskTracker再收回来,jobTracker就相对比较忙。因为它是单点。
主从集群它的主节点是单节点就一定会有两个问题
在hdfs最初的版本,它的namenode也是单点,也有两个问题
第一自己是不是会挂呀?单点故障。
第二他是不是能力是有限对不对?他自己就这样能力,内存,网卡,CPU
除了这两个问题之外,还有一个问题,
第3个问题就是,我们的mapreduce框架就这个模型下,还有另外一个问题,就是jobTracker包含了资源管理和任务调度两个大功能。
那么未来其实在这个集群里边,你公司新用户我花了几十万几百万弄了一个集群,这么多机器,不可能只跑一类计算程序,可能还有其他的特征的计算程序,那些计算程序,未来可能也是分布式的,他们也会向一些节点去分发一些任务。
如果另外一套计算框架,想用那个集群,只要是计算框架,根据刚才的推理。计算框架都需要资源的感知,然后任务调度。那么另外一个计算程序,因为这边耦合住内关联了,jobTracker同时包含资源和调度,那么另外一个计算程序,也得写资源管理和任务调度。就等于重复造轮子,它也得写一个进程类似于jobTracker,里面也要有资源的管理和任务调度。但是这时候你会发现在同一个集群当中有两个资源管理,且是两套,那么这时候其实他们在看着一堆东西,但是他们因为是隔离的独立的,其实他们对资源的理解是不完整的,也就是说当这边如果提交一个程序,然后认为第一台空余,就把任务分发过去了,但是他去调度的,如果另外有一套程序也有一个资源资源调度的话,那么其实这边分配的任务在他那边是不知道的,因为相应的这个jobTracker会有两个副本,那么从角色也是有两个的。所以他那边的主是不会和他这个连接,然后等于这个节点上会有另外一个从的任务的角色,会和那个主做另外一套心跳汇报,所以他们两个人并不知道,并不能感知对方有分配到什么任务,在占用这个资源,最终会一个小问题,就是什么呀,资源会有冲突,争抢,不均衡。
这些事情都聊完之后,最终会有一个小问题。jobTracker有三个问题。
1.它是单点的,会有单点故障
2.压力过大,调度的不是很快会延迟,fullGC等其他的问题
3.jobTracker集成了资源管理,任务调度。两者耦合,带来的弊端:未来新的计算框架不能复用资源管理,重复造轮子。
不能复用会有两个问题:
第1个是重复到轮子,另外一个计算框架要想跑的基于hadoop生态的话,他还得重写资源管理这块
第2个因为重复造轮子各自实现资源管理,但是他们部署在同一批硬件上。因为隔离所以不能感知对方的使用情况,那么最终会带来一个结果,资源争抢。

上面给你讲这个知识点,这个这个整个流程是hadoop1.x的时候,现在已经被淘汰了。
但不要紧,要学的是学习方法和技术发展的路线,这个问题是怎么解开的,出现了hadoop2, 2.x的时候是要去解决上面这个问题。先不着急学新的东西,这个东西被淘汰,并不是说完全就把它删掉了,这里边是最终是要对它做调整,所以你要学的在未来,你可能遇到一些技术问题,你会有一种解决方案,解决方案其实是在你学习新知识过程当中,学他这个技术的发展路线,变化过程,其实这个过程当中也是在学习经验。

模型讲完了之后,最关注的就是模型变现的过程,就是计算向数据移动实现的过程。
思路:(因果关系导向学习)
【计算要向数据移动】
->哪些节点可以去呢(需要有整体资源的把控)
->确定了节点后对方怎么知道呢(任务调度),还有比如有一个失败了,应该重新在那个节点重试
->来个jobTracker搞定了这两件事,但是,后来,问题也暴露了。。。

看hadoop技术的发展史是如何解决这一问题的。还是教你学习方法,未来你学技术的时候可能会上来看东西叫做架构图,就框架那个图或者叫架构图。
yarn架构,很简单的描述,我说咣当就给你甩出来一张图,完事了。
从今天的课你要学到一种学习方法,未来除了这样的图,还会看到很多的不同技术的不同的架构这样的图,那么你当看到图的时候,你要养成一种习惯,别说自己看不懂,你要找到一些规律啊,首先它这个图画的是比较科学的啊,因为它用了很多不同的颜色来区分。
有一系列的颜色,相同颜色是成一套体系的,蓝色的若干几个,红色的又是若干的几个,紫色的又是若干的几个。所以说我们现在的颜色一层层地剥离这张架构图你看的时候,红色和紫色都有一个客户端的名词,所以这些角色我们都可以先给它抹掉,那么留下一个没有客户端概念的,比如这里面有一个Resource Manager和Node Manager,通过名字可以得出一个结论来,就是资源这块,蓝色是负责资源的,如果你把红色和紫色抹掉之后,你会发现他们是一个多个点对一个点的连接的过程,然后这时候你可以得出一个结论,它是一个什么架构?是不是一个主从架构。以后看任何技术啊,只要是大数据里的技术,你都要看到架构图。
上来第一件事情先区分它的架构是一种什么架构,是主从架构还是无主架构。
后面也会有那种无主的,一堆平等角色的,他们里边会有一种复杂的知识理论,但是都是套路,你学会一个认真能学到学习方法,后边的东西都很容易条件反射。
那么这里面Resource Manager和Node Manager就是我们hadoop项目当中新开发的一个模块叫做yarn,它是做什么的,它就是将我们曾经的hadoop当中的jobTracker这套服务当中的资源管理独立出来了,就是资源管理。
刚才说了资源管理这一块,耦合到你的计算框架里去了,那么别的计算框架要重复开发资源管理,且重复的资源管理还是隔离的,所以还不能感知对方的资源的使用情况会有这种资源争抢和冲撞的现象。
所以这时候啊,在软件工程学当中都会有这么一个概念叫做解耦,就是将我们重复的东西割离出来,变成一个独立的大家共享的服务。
所以这时候hadoop就将我们的资源管理抽出来,变成了一个yarn这么一个架构框架,比较通俗的理论知识就是拆解和解耦的一个过程,那么hadoop当中独立起了一个yarn之后,这个yarn和mapreduce是无关的,这个yarn是一个独立的资源层,它在资源层之上可以支持我们的mapreduce去申请资源,也可以支持spark和其他的计算程序去在他这上面去申请资源。不同的计算框架从一个地方去申请资源。从不同节点去启动任务,这个时候他们是有一个统一视图的,再也不会说两个人都不知道,在同一个节点去启动了各自的任务,有争抢这种现象。
当yarn这个资源框架在资源管理这一块我们知道之后,那么资源层和计算层之间是一种什么关系?
当一个技术的诞生,不应该对另外一个技术有过多的这个影响,这时候来回顾,在曾经老版本的计算框架当中,它有两个功能是资源管理和任务调度,其实现在只是干涉到资源这块的切割出来,所以对它的任务调度这一块应该是影响不大,所以其实这个时候刚才的知识点有些东西还是可以复用的。
在mapreduce on yarn的时候(mapreduce基于yarn之上),它的运行方式如何运行?
左边两个客户端他们分别有两个颜色,一个颜色就代表一个客户端。先看红色的客户端,注意还是我们mapreduce的客户端,他要做的事情还是那些事情,第一他要做切片清单,只有他算出了多少个切片以及每个切片可以去到哪去,有这个清单了,未来才可以和我们资源层去申请资源,你没有清单的话,你就根本不知道有多少个map且每个map应该去到哪去啊,就没有这个决策。所以客户端还是做切片清单的计算,还是要将我们的配置生成xml文件,还是要将这些资源上传到hdfs,这一个过程在客户端变化不大。
那么剩下来之前客户端联系的谁啊?
在这张图当中你还看到jobTracker和taskTracker吗?
是不是就再也没有看到了,等于是把那个曾经的耦合的角色淘汰掉,换了一批新的角色,那么客户端曾经联系jobTracker,现在换成联系谁?
联系resource manager
因为联系完resource manager之后,resource manager会帮我们在集群当中挑一台不是很忙的节点,有资源的节点,帮这个客户端创建一个角色,这个角色叫做application master。英文单词就是应用程序的master主节点。
就是我们计算程序的主节点,曾经的job Tracker叫做长服务,集群一开机jobTracker角色就得启动,什么时候集群关闭了,这个角色才被杀死或者退出,是一直在运行的长服务。没有计算程序的时候也是在运行的,只不过没人提交作业而已。
那么现在有了yarn之后没有jobTracker了,但是任务调度的事还得做。那么这个时候是只要有计算的时候,计算发生的时候才会出现一个application master,那么这个application master是什么?
就是约等于jobTracker,为什么是约等于?因为是一个阉割掉资源管理的jobTracker只留下了他的任务调度的那一套逻辑代码。
曾经的长服务,变成了按需启动的服务了,注意那个流程,客户端,通过resource manager,因为resource manager收集了所有node manager汇报的资源,知道哪些节点的资源的使用情况,所以这时候resource manager有能力挑一个不忙的地点来启动一个application master,application master做什么事情?曾经jobTracker怎么干,他依然还按照这个流程走,application master从hdfs下载切片清单的文件,但是注意了,曾经是jobTracker自己完成了自己决策,就是每一个任务应该需要哪里,但是现在application master里边是一个被阉割的,没有资源模块。没有人向他汇报过,这个集群里面有多少个节点,每个节点的资源情况。
所以它必须依赖yarn层,依赖resource manager,这个时候application master会拿着清单访问resource manager说大哥我这有一个清单,有几十个map要跑,每个map可以去到若干个节点,你根据你掌握的资源情况给我拍板,哪些节点可以去哪个map。
这三者的一个关系,客户端和resource manager和application master。那么这时候resource manager肯定知道所有资源的情况,他一看清单之后,根据每个节点数据每个节点剩余的资源谁合适,最终会决策。
决策之后,曾经是TaskTracker去jobTracker去拉取任务,但是他们要隔一个心跳三秒,所以mapreduce启动任务的速度并不是很快,但是现在有了resource manager之后,清单这个事情搞定了。是由resource manager向node manager,因为node manager是每一个节点的管理角色了,管理资源的,发消息说,你这边可以未来跑一个任务,你这边可以未来跑一个任务,你这边可以未来跑两个任务。红色这边跑一个,这边跑两个,最终去哪儿,计算向哪儿移动是由他决定的,最终也是他通知了node manager,resource manager既然叫做资源管理层,它对资源有一个抽象,用一个东西来抽象代表资源,因为资源的确是一种虚幻的东西,内存这东西它就是一个数值。
怎么来说一个任务应该是消耗了这个节点多少资源呢?它用一个进程来代替资源的定义和最终的约束,这个东西叫做container,就是容器的意思。
想想你家里如果打开柜子里面,有大盒子小盒子,那么一个抽屉就是一个完整的资源,里面每一个容器(大中小的盒子)其实占有了不同的空间。所以这时候其实就以container,其实container是一个虚幻的东西,它未来也是一个物理的。虚幻的时候,它是一个类,是一个对象,里面有一些属性,属性里边写了一些,比如说要消耗1G内存还是几G内存,要占用几个盒,占用多少东西。这是一个逻辑的container,一个资源的描述。那么最终启动进程的时候,这个进程可以消耗的资源也是按照这个对象来定义的。来监控的。这些都是一些JVM进程,他们被node manager启动之后,他们做一件事情,要反向注册给application master,因为最终我们的任务是要分发出去跑的,application master是临时被启动的,任何node manager没有和他做过连接。所以他不知道有多少个节点,只能通过resource manager分配的container,向他反向注册的时候,application master就知道了,原来这么多地方,有这么多容器,未来是可以跑我们的任务的。
这是一个反向注册,也就是说resource manager分配container可能是一个进程,进程其实就是一个容器级的了。它现在跑起来,然后和application master做反向注册,注册之后application master就知道了集群当中有多少个槽位,有多少个容器是归它使用的。
当application master知道了有这么多地方,这么多容器,这么多进程在运行了,那么最终使用application master来做决策,最终将mapTask发送到对方,也是一个消息发送过去,最终也是由这边的节点从hdfs把jar包拿回来,在已启动进程里面,Java当中有一个非常优秀的东西叫做反射。是由已启动的进程,来反射jar包当中的mapTask类变成对象,调用里面的方法来运行。我们的逻辑就在container这个进程当中被变现了。那么最终它的整个的框架就是这么一个过程。
那么以上它那个关于红色这个客户端的一个程序启动流程,我再说一遍。
整个左边流程,客户端先做他该做的事情。切片清单的计算,配置文件,然后等等这些资源jar包上传到hdfs,最终通知resource manager,然后resource manager挑一个不忙的节点启动application master。application master从hdfs取回切片清单,反向从resource manager申请container。resource manager据自己掌握的资源情况,然后来分配最合适的节点去启动一批container,container是通过node manager来启动的,他们之间是通过消息发送来确定它的启动的,那么container是逻辑的,也是物理的。逻辑上container就是一个对象,它有一些属性定义了,未来在这个节点当中要消耗多少内存,多大cpu,多大的带宽。它也是物理的,就是最终会启动这样一个进程,JVM进程是按照这个资源申请来划分的,比如堆,堆大小如果container定义了只能使用3G的话,堆大小就是3G,启动了这个jvm进程,container就是物理的,那么这些container启用之后,他们会反向注册给我们的application master,只有反向注册成功之后,application master才知道在这个集群当中有多少个位置是可供他去调度的。所以最终由application master将mapTask/reduceTask这些task任务,最终要通过消息调度给这些container,但是这时候注意了,并不是由application master把这些任务代码发出去的,消息发过去之后,是由这边的节点进程从fdfs取回jar包和配置文件,然后通过反射的方式得到对象运行方法,我们的逻辑在container中变现,实现出来。
所以application master其实也是一个container。
现在你得到一个结论,在yarn当中资源都是由container来代表的,container来约束的,在客户端申请resource manager启动application master的时候,也是resource manager挑了一个不忙的节点,和node manager发了一个消息说,你帮我启动一个啥啥啥,那么这时候node manager其实也是先启动一个container反射了一个application master类,然后变现变成一个对象跑起来了。
反向注册,container其实就是一个进程,它是要和application master通信的啊,是这么一个注册的过程的。
注册你就想一个集群里边,就比如说你在中国每一个城市,然后都会有一个你自己一个团体里面的一个成员,然后这些人如果不跟你联系的话,你怎么知道有这么多人是和你一个团伙的,他们是不是给你打电话,然后之后你再给他打电话说让他们干什么事情。你就等于是小队长,他们就是小跟班。
刚才是描述了一个这个大体的流程走完了之后,再看另外一个东西。左边有两个客户端,一个是红色一个是紫色。这时候来观察一个特征,就是前一个版本的时候,问题是怎么去解决的,那么当红色走完之后,对于紫色具有相同的流程。比如紫色的客户端通过resource manager会申请到一个紫色的application master,然后application master依然会去做资源申请,依然会启动container,然后application master和container之间依然是一个通信,然后来分配任务的一个过程。这时候你会发现,曾经的版本当中是只有一个jobTracker,他负责所有客户端的任务调度,那么现在变成了每一个客户端要起一个自己的程序的时候,都会有一个为自己做调度的一个独立的application master,而且会由资源层很均衡的散在我们不同的节点里。
在这样的一个模型下有一个好处,如果两个同时在运行,其中的一个红色的application master挂掉了,这个时候紫色那边还是完整的不受影响,在单点故障上,已经从曾经的一个单点负责所有任务,这个单点挂掉之后所有任务调度失败,现在变成什么力度了?
以一个计算程序为单位的一个调度,各自调度各自自己的。其中一个application master挂掉的话,对另外一个不受影响,这是一个维度。
除了这一点,曾经的一个jobTracker的调度所有的任务,监控所有的资源,它的压力比较大,到现在每一个计算程序有自己独立的调度程序,而且这个调度程序只负责了一个程序自己的一批任务。不去管其他程序的任务之后,同样是JVM进程,它的压力也是指数级降低变得很小了。再回忆曾经jobTracker的3个问题
1.单点故障,降级成每个计算程序了,而不是全部计算程序。
2.压力过大,降级成每一个阶段程序自己调度,不负责别人。
3.耦合度的问题,切割出一个yarn之后,任何的计算框架只要遵从yarn资源框架的通信标准,开发自己相应调度程序的application master的代理,实现类子类。都可以在一个资源层上跑起来了,也不需要重复造轮子了,而且资源这个层面是统一视图,就这一批相同的资源,每一个计算框架都能知道,都由他来管理,
三个问题是不是都解决了。
提问1:从图上来看,一个node可以启动多少container?
container是一个资源的描述,一个节点可能有10个核心,10G内存,mapreduce默认情况下,它的一个task是只消耗1个核心,1g内存,所以一个节点上起码是可以跑10个的
提问2:一个node挂机了,所有的任务都完蛋了。
这是的确的,假设下面这个节点挂机了,整个物理服务器挂机了,那么这两个container都完蛋了。假设上面这个节点挂机了,两个计算程序里面各自的application master和container都完蛋了。这个时候注意有一个机制,在计算框架当中有失败重试的机制,在task级别有失败重试的,比如说红色有三个container,有俩挂掉了主机,这时候application master,因为汇报心跳,注册的过程发现他已经挂掉了。挂掉之后是由application master重新拿着曾经他们的两个任务清单,重新去申请资源。resource manager再挑两个container出来,在一些存活的节点上,这时候再重新注册,那个失败的任务重跑。
而且这个里面连application master都失败重试,因为application master再也不是像jobTracker一样,我们启动一个脚本启动起来的。是由资源层把它调度起来的,是资源层resource manager调度node manager,启动了一个container。container反射了一个application master。那么这个application master如果挂掉的话,再resource manager中会有一个application master manager管理器能知道它,因为它会有一个反向注册申请资源的过程,也会知道它的挂掉,这时候resource manager会从其他节点再启动一个application master。
所以再有了资源管理层之后,一定要明白它叫资源管理,他能管的事,首先明白啥叫资源,如果资源能明白了,能管的事就非常清晰了。
那么在yarn当中一切皆资源,我们的任务和我们调度都是由container变现出来的,所以他们都叫做资源。
提问3:服务器具体是什么?
这就是另外一个层次的话题了,服务器可以是虚拟机,也可以是docker。
application master挂掉了只是它的进程挂掉了,这些进程(container)是不受影响的,只不过他们找不到主了,那么这时候由resource manager重新启动一个主(application master)的话,他们会重新注册,因为消息都能发过去,这都不是问题。

那么来回顾这张图,其实很通用的一个知识点,那么这张图中你会发现yarn架构当中的resource manager和node manager他给你画了一个主从结构。
凡是主从结构条件反射都不用别人给你提醒第1点就要想,它的主是单点,resource manager是单点,它是不是具备单点故障,如果他挂掉的话是不是就会有问题?而且他是不是也存在压力过大的问题?这应该是条件反射,就是我一开始的时候问我说他这个图是什么架构?指出了是主从,但是从来没有人说,这个主是不单点的这个问题。
但是这个时候再来思考一个时间轴,从hadoop1.x开始,蔓延了一段时间之后,到hadoop2.x,在hadoop2.x出来的时候已经发现了, hdfs是不是具备单点故障,所以在hadoop2.x当中弥补更新了一些角色,比如说zKFC,还有这个hr的hp类的事情对不对?而且hadoop2.x的时候才提出了yarn这个框架,在提出yarn框架的时候,已经知道这个项目当中另外一个东西具备单点故障了,要开发出可靠性,所以这时候在yarn开发的时候,人家作者已经想到这个问题了,所以yarn的resource manager其实是支持ha的,只不过这张图没有画而已。
再条件反射,主从架构,主是单点,在大数据里面那个单点的东西它一定会怎么解决?是不是主备的概念。和hdfs很像,resource manager也是有一个主,有一个备。只要是主备的话,最终都都是靠什么来实现的?
主备的切换,抢主的过程,在分布式情况下一定会使用zookeeper。把所有学过的知识捻合起来,每个技术在做一件什么事情,在很多地方都会重复出现,一定要养成条件反射的过程。
总结:
hadoop2.x yarn
模型:
container容器
架构:

模型:hdfs有块,mapreduce有task,有阶段,在yarn中提出了container容器的概念,注意,这里的容器不是docker的容器,docker是一种容器技术,在yarn中的容器是一个虚幻的东西,这个容器可以是虚的,也可以是物理的。对于虚的来说,可以想象成一个对象,对象有属性:属性定义了CPU,内存,IO的量,有一系列属性的定义。除了有资源的定位,还有归属于哪个node manager,在这个node manager当中要消耗多少内存,多少CPU,多少IO量,这是一个虚的定义。它也可以是物理的,这个物理可以是一个JVM进程,操作系统进程可以和操作系统挂钩了,有两种实现方式对资源的管理和监控。(1,解耦的资源管理,node manager会有线程监控container资源情况,有没有超标,超额的时候由node manager直接kill掉,由node manager直接杀死物理的JVM进程,如果杀死的话container里跑的任务就等于异常退出失败了,计算框架都有失败重试的概念,这个时候里面跑的任务会被调度到别的节点的container里面,但在这个里面都超额了,调到别的节点最终也会超额被杀死,会出现一个问题到哪都杀死,但是重试不是无限的,重试个3次或6次都失败了之后,可能整个计算程序最终的命运也是跑失败。超额是什么情况产生的呢?并不是框架有bug,不是container带来的问题,是在申请资源的时候,给container的资源分配小了,mapreduce默认一个task任务是1G内存,但有可能在代码里new出了一个2G的字节数组,代码没有变直接就超额被杀死了,这种方式太暴力了,线程是一种消耗比较大的方式)
(2,通过cgroup内核级技术,做资源控制,在启动JVM进程,由内核kernel约束死未来操作系统级的jvm进程只能使用多大的内存寻址空间,就能减少线程监控的事情)
(3,只要是进程,docker容器就是进程即容器的概念。所有还可以整合docker)
问题:写代码的时候要提前计算资源占用么?
这个是肯定的。如果什么事都那么简单,薪资也不会那么高。提交任务的时候要指定内存大小,这也是肯定的。这都是可以传参数的,只要是门语言,有默认配置,就一定会有用户自定义个性化配置,用户都可以干预。
在后面学习spark的时候,这个就更强了,在spark程序要启动的时候,要决定这个进程未来核的数量,内存的数量,容器的启动个数等等一系列的很多维度都要去控制,如果稍加控制不好,某个参数忘记设置了,可能都不是内存溢出,就是内存不够了,程序跑到最后连输出都没有,会很诡异。
架构:模型实现的问题。
只要是架构就要有角色:
resource manager:主角色
node manager:从角色
只要是主从之间,一定是有心跳的,resource manager 负责整体资源的管理,node manager从角色要向resource manager 汇报心跳,提交自己的资源情况。这是最粗略的描述。
MR运行 mapreduce on yarn
1.MR的客户端启动之后,切片清单,配置,jar包,上传的hdfs
访问resource manager 来申请application master
2.resource manager 选择一台不忙的节点,启动 通知我们的node manager启动一个container,在里面反射一个MR的application master类
3.启动MR的application master,从hdfs下载切片清单,向resource manager申请资源,
4.最终由resource manager根据自己掌握的资源情况,得到一个确定清单,通知node manager来启动container
5.container启动后,会反向注册到已经启动的MRapplication master进程,这个时候才知道集群里有多少个container可以被自己调度。
6.由MRapplication master(曾经的JobTracker阉割版不带资源管理)最终将任务Task发送给container(发送的是消息)
7.container会反射相应的task类为对象,调用方法执行,其结果就是我们的业务逻辑代码的执行过程
8.计算框架都有任务Task失败重试的机制,可以人为干预关闭
结论:
问题:
1.单点故障(曾经是全局的,JobTracker挂了,这个计算层没有了调度,所有的作业都失败了)
有了yarn之后,每一个application有一个自己的applicationMaster调度!(计算程序级别)
yarn支持applicationMaster失败重试~!
2.压力过大
yarn中每个计算程序自有applicationmaster,每个applicationmaster只负责自己计算程序的任务调度,轻量了
application masters是在不同的节点中启动的,默认有了负载的光环
3.集成耦合度的问题
因为yarn只是资源管理,不负责具体的任务调度
是公立的,只要计算框架继承yarn的AppMaster,目的都能和resource manager统一通信,大家都可以使用一个统一视图的资源层~!!!

总结感悟:
在两次框架的变化当中,在前一个框架中,有JobTracker和TaskTracker这些角色属于mapreduce,在升级到hadoop2.x之后(MapReduce on yarn)那些角色消失了,相应的要明白,计算框架里,客户端,application master以及container里的一些task任务,也就是客户端调度和任务,它们都变成了临时服务。计算框架再也没有自己的长服务了,曾经自己的长服务被切割出去,然后阉割了一下,只留下了一些资源层面的长服务,这些长服务不是计算框架的,是yarn资源层的。
从1.x到2.x
在未来谈集群部署的时候一定要明白一个概念,曾经的JobTracker和TaskTracker是MapReduce的长服务(一直运行的)
2.x之后,没有了这些服务
相对的MR的cli,调度,任务,这些都是临时服务了

猜你喜欢

转载自blog.csdn.net/m0_48758256/article/details/108558329