持续更新中
版本 | 更新时间 | 更新内容 |
---|---|---|
V1.1 | 2022-07-02 | Spark |
V1.0 | 2022-06-02 | Hadoop+Zookeeper+ETL+即席查询+任务调度 |
文章目录
- 持续更新中
- 一、Hadoop篇
- (一)HDFS
- 1. 请说下HDFS读写流程
- 2、HDFS 的组织架构以及它们的作用
- 3、HDFS中的NameNode和SecondaryNameNode的工作原理
- 4、HDFS中块的大小为什么设置成128M?
- 5、HDFS 集群安全模式
- 6、HDFS 在读取文件的时候,如果其中一个块突然损坏了怎么办
- 7、HDFS 在上传文件的时候,如果其中一个 DataNode 突然挂掉了怎 么办
- 8、NameNode 在启动的时候会做哪些操作
- 9、在NameNode HA 中为什么会出现脑裂问题?怎么解决
- 10、Secondary NameNode的工作机制是怎样的
- 11、当Secondary NameNode 不能恢复 NameNode 的全部数据时,要如何保证 NameNode 数据存储安全
- 12、小文件过多会有什么危害,如何避免
- (二)Mapreduce
- (三)Yarn
- 二、Zookeeper篇
- 三、ETL篇
- 四、数据仓库篇
- 五、即席查询篇
- 六、任务调度篇
- 七、Spark篇
一、Hadoop篇
Hadoop这块主要围绕Hadoop的三架马车(HDFS-存储,MapReduce-计算,Yarn-资源调度)展开。
(一)HDFS
1. 请说下HDFS读写流程
这个问题必须记住。因为都是从HDFS读写流程中引申出来的
HDFS写流程
1)client客户端发送上传请求,通过RPC与namenode建立通信,namenode检查该用户是否有上传权限,以及上传的文件是否在hdfs对应的目录下重名,如果这两者有任意一个不满足,则直接报错,如果两者都满足,则返回给客户端一个可以上传的信息
2)client根据文件的大小进行切分,默认128M一块,切分完成之后给namenode发送请求第一个block块上传到哪些服务器上
3)namenode收到请求之后,根据网络拓扑和机架感知以及副本机制进行文件分配,返回可用的DataNode的地址
注:Hadoop 在设计时考虑到数据的安全与高效, 数据文件默认在 HDFS 上存放三份, 存储策略为本地一份,同机架内其它某一节点上一份, 不同机架的某一节点上一份
4)客户端收到地址之后与服务器地址列表中的一个节点如A进行通信,本质上就是RPC调用,建立pipeline,A收到请求后会继续调用B,B在调用C,将整个pipeline建立完成,逐级返回client
5)client开始向A上发送第一个block(先从磁盘读取数据然后放到本地内存缓存),以packet(数据包,64kb)为单位,A收到一个packet就会发送给B,然后B发送给C,A每传完一个packet就会放入一个应答队列等待应答
6)数据被分割成一个个的packet数据包在pipeline上依次传输,在pipeline反向传输中,逐个发送ack(命令正确应答),最终由pipeline 中第一个 DataNode 节点 A 将 pipelineack 发送给 Client
7)当一个 block 传输完成之后, Client 再次请求 NameNode 上传第二个 block ,namenode重新选择三台DataNode给client
HDFS读流程
1)client向namenode发送RPC请求。请求文件block的位置
2)namenode收到请求之后会检查用户权限以及是否有这个文件,如果都符合,则会视情况返回部分或全部的block列表,对于每个block,NameNode 都会返回含有该 block 副本的 DataNode 地址; 这些返回的 DN 地址,会按照集群拓扑结构得出 DataNode 与客户端的距离,然后进行排序,排序两个规则:网络拓扑结构中距离 Client 近的排靠前;心跳机制中超时汇报的 DN 状态为 STALE,这样的排靠后
3)Client 选取排序靠前的 DataNode 来读取 block,如果客户端本身就是DataNode,那么将从本地直接获取数据(短路读取特性)
4)底层上本质是建立 Socket Stream(FSDataInputStream),重复的调用父类 DataInputStream 的 read 方法,直到这个块上的数据读取完毕
5)当读完列表的 block 后,若文件读取还没有结束,客户端会继续向NameNode 获取下一批的 block 列表
6)读取完一个 block 都会进行 checksum 验证,如果读取 DataNode 时出现错误,客户端会通知 NameNode,然后再从下一个拥有该 block 副本的DataNode 继续读
7)read 方法是并行的读取 block 信息,不是一块一块的读取;NameNode 只是返回Client请求包含块的DataNode地址,并不是返回请求块的数据
8) 最终读取来所有的 block 会合并成一个完整的最终文件
2、HDFS 的组织架构以及它们的作用
1、Client:客户端
(1) 切分文件。文件上传 HDFS 的时候,Client 将文件切分成一个一个的 Block, 然后进行存储
(2)与 NameNode 交互,获取文件的位置信息
(3)与 DataNode 交互,读取或者写入数据
(4)Client 提供一些命令来管理 HDFS,比如启动关闭 HDFS、访问 HDFS 目录及 内容等
2、NameNode:名称节点,也称主节点,存储数据的元数据信息,不存储具体 的数据
(1)管理 HDFS 的名称空间
(2)管理数据块(Block)映射信息
(3)配置副本策略
(4)处理客户端读写请求
3、DataNode:数据节点,也称从节点。NameNode 下达命令,DataNode 执行实 际的操作
(1)存储实际的数据块
(2)执行数据块的读/写操作
4、Secondary NameNode: 并非 NameNode 的热备。当 NameNode 挂掉的时候, 它并不能马上替换 NameNode 并提供服务
(1)辅助 NameNode,分担其工作量
(2)定期合并 Fsimage 和 Edits,并推送给 NameNode
(3)在紧急情况下,可辅助恢复 NameNode
3、HDFS中的NameNode和SecondaryNameNode的工作原理
- fsimage是namenode内存中元数据序列化形成的文件,edits记录客户端更新元数据信息的每一步操作。
- 第一次启动namenode格式化后,创建fsimage和edits文件,如果不是第一次启动,直接加载编辑日志和镜像文件到内存
- 客户端对元数据进行增删改的请求
- namenode记录操作日志,更新滚动日志
- namenode在内存中对数据进行增删改
- secondarynamenode 询问namenode是否需要chkpoint
- secondarynamenode请求执行checkpoink
- namenode滚动正在写的edits文件
- 将滚动前的编辑日志和镜像文件拷贝到secondarynamenode
- 生成新的镜像文件fsiamge.checkpoint
- 拷贝fsimage.checkpoint到namenode
- namenode将fsiamge.chkpoint重新命令成fsimage
4、HDFS中块的大小为什么设置成128M?
Hdfs中平均寻址时间为10ms
寻址时间是传输时间的1%时为最佳状态,所以最佳传输时间为1s
目前磁盘的传输速率普遍为100mb/s,因此100mb/s*1s=100mb,因此设置块大小为128mb
寻址时间 : 10ms
传输时间 : 10 ms *1000 = 1s
磁盘传输速率 :100MB/ s
每秒传输大小 : 100MB/s * 1s = 100MB
因此最终块的大小设置为 128 MB
5、HDFS 集群安全模式
安全模式是一种保护机制,处于安全模式时,NameNode对外只提供读操作,不能增删改等操作。
- NameNode 启动时,便会进入到安全模式。
- NameNode首先将镜像文件载入内存,并执行 EditLog 中的操作,一旦内存中成功建立元数据镜像,则会创建一个新的 Fsimage和 空的editLog 文件,此时,NameNode开始监控DataNode 请求,这个过程一直处于安全模式。
- 检查数据的完整性, 假设设置的副本数是 5(dfs.replication =5) , 但是实际只存在3 个副本,那么比例就是 3/5 = 0.6。
在hdfs-default.xml中设置安全模式最小副本数 dfs.safemode.threshold.pct = 0.999f, 而副本率 0.6 明显小于 0.999,
那么系统会自动复制副本到其他的 DataNode上。如果系统中有8 个副本,但是设置的是5个副本,会删除掉多余的副本。 - 正常情况下,安全模式运行一段时间会自动退出的。
查看安全模式状态:hdfs dfsadmin –safemode get
进入安全模式:hdfs dfsadmin –safemode enter
离开安全模式:hdfs dfsadmin –safemode leave
等待安全模式:hdfs dfsadmin –safemode wait
6、HDFS 在读取文件的时候,如果其中一个块突然损坏了怎么办
客户端读取完 DataNode 上的块之后会进行 checksum 验证,也就是把客户端读 取到本地的块与 HDFS 上的原始块进行校验,如果发现校验结果不一致,客户端 会通知 NameNode,然后再从下一个拥有该 block 副本的 DataNode 继续读取。
7、HDFS 在上传文件的时候,如果其中一个 DataNode 突然挂掉了怎 么办
- 客户端上传文件时与DataNode建立pipeline管道,管道正向是客户端向DataNode 发送的数据包,管道反向是 DataNode 向客户端发送 ack 确认,也就是正确接收到数据包之后发送一个已确认接收到的应答。
- 当 DataNode 突然挂掉了,客户端 接收不到这个 DataNode 发送的 ack 确认 ,客户端会通知 NameNode,NameNode 检查该块的副本与规定的不符, NameNode 会通知 DataNode 去复制副本,并将挂掉的 DataNode 作下线处理,不 再让它参与文件上传与下载。
8、NameNode 在启动的时候会做哪些操作
NameNode 数据存储在内存和本地磁盘,本地磁盘数据存储在 fsimage 镜像文件 和 edits 编辑日志文件
- 首次启动 NameNode
- 格式化文件系统,为了生成 fsimage 镜像文件
- 启动 NameNode
(1)读取 fsimage 文件,将文件内容加载进内存
(2)等待 DataNade 注册与发送 block report - 启动 DataNode
(1)向 NameNode 注册
(2)发送 block report
(3)检查 fsimage 中记录的块的数量和 block report 中的块的总数是否相同 - 对文件系统进行操作(创建目录,上传文件,删除文件等)
(1)此时内存中已经有文件系统改变的信息,但是磁盘中没有文件系统改变的信息,此时 会将这些改变信息写入 edits 文件中,edits 文件中存储的是文件系统元数据改变的信息。
- 第二次启动 NameNode
- 读取 fsimage 和 edits 文件
- 将 fsimage 和 edits 文件合并成新的 fsimage 文件
- 建新的 edits 文件,内容为空
- 启动 DataNode
9、在NameNode HA 中为什么会出现脑裂问题?怎么解决
为什么会出现脑裂问题
- 假设 NameNode1 当前为 Active 状态,NameNode2 当前为 Standby 状态。如果某一时 刻 NameNode1 对应的 ZKFailoverController 进程发生了“假死”现象,那么 Zookeeper 服务端会认为 NameNode1 挂掉了。
- 根据前面的主备切换逻辑,NameNode2 会替代 NameNode1 进入 Active 状态。但是此时 NameNode1 可能仍然处于 Active 状态正常运行,这样 NameNode1 和 NameNode2 都处于 Active 状态,都可以对外提供服务。这种 情况称为脑裂
如何解决脑裂问题
- 脑裂情况,对于 NameNode 这类对数据一致性要求非常高的系统来说是灾难性的,数据会发生错乱且无法恢复。Zookeeper 社区对这种问题的解决方法叫做 fencing, 中文翻译为隔离,也就是想办法把旧的 Active NameNode 隔离起来,使它不能 正常对外提供服务。
10、Secondary NameNode的工作机制是怎样的
Secondary NameNode 是合并 NameNode 的 edit logs 到 fsimage 文件中; 它的具体工作机制:
- Secondary NameNode 询问 NameNode 是否需要 checkpoint。直接带回 NameNode 是否检查结果
- Secondary NameNode 请求执行 checkpoint
- NameNode 滚动正在写的 edits 日志
- 将滚动前的编辑日志和镜像文件拷贝到 Secondary NameNode
- Secondary NameNode 加载编辑日志和镜像文件到内存,并合并
- 生成新的镜像文件 fsimage.chkpoint
- 拷贝 fsimage.chkpoint 到 NameNode
- NameNode 将 fsimage.chkpoint 重新命名成 fsimage 所以如果 NameNode 中的元数据丢失,是可以从 Secondary NameNode 恢复一部 分元数据信息的,但不是全部,因为 NameNode 正在写的 edits 日志还没有拷贝 到 Secondary NameNode,这部分恢复不了
11、当Secondary NameNode 不能恢复 NameNode 的全部数据时,要如何保证 NameNode 数据存储安全
这个问题就要说 NameNode 的高可用了,即 NameNode HA 一个 NameNode 有单点故障的问题,那就配置双 NameNode,配置有两个关键点, 一是必须要保证这两个 NN 的元数据信息必须要同步的,二是一个 NN 挂掉之后 另一个要立马补上。
- 元数据信息同步在 HA 方案中采用的是“共享存储”。每次写文件时,需要将日志同 步写入共享存储,这个步骤成功才能认定写文件成功。然后备份节点定期从共享存储同 步日志,以便进行主备切换。
- 监控 NN 状态采用 zookeeper,两个 NN 节点的状态存放在 ZK 中,另外两个 NN 节点 分别有一个进程监控程序,实施读取 ZK 中有 NN 的状态,来判断当前的 NN 是不是已 经 down 机。如果 standby 的 NN 节点的 ZKFC 发现主节点已经挂掉,那么就会强制给原 本的 active NN 节点发送强制关闭请求,之后将备用的 NN 设置为 active。
如果 再问 HA 中的 共享存储 是怎么实现的?
- 可以进行解释下:NameNode 共享存储方案有很多,比如 Linux HA, VMware FT, QJM 等,目 前社区已经把由 Clouderea 公司实现的基于 QJM(Quorum Journal Manager)的方案合并 到 HDFS 的 trunk 之中并且作为默认的共享存储实现。
- 基于 QJM 的共享存储系统主要用于保存 EditLog,并不保存 FSImage 文件。FSImage 文件 还是在 NameNode 的本地磁盘上。QJM 共享存储的基本思想来自于 Paxos 算法,采用多个 称为 JournalNode 的节点组成的 JournalNode 集群来存储 EditLog。每个 JournalNode 保存同样的 EditLog 副本。
- 每次 NameNode 写 EditLog 的时候,除了向本地磁盘写入 EditLog 之外,也会并行地向 JournalNode 集群之中的每一个 JournalNode 发送写请求, 只要大多数 (majority) 的 JournalNode 节点返回成功就认为向 JournalNode 集群写入 EditLog 成功。如果有 2N+1 台 JournalNode,那么根据大多数的原则,最多可以容忍有 N 台 JournalNode 节点挂掉
12、小文件过多会有什么危害,如何避免
-
Hadoop 上大量 HDFS 元数据信息存储在 NameNode 内存中,因此过多的小文件必 定会压垮 NameNode 的内存。
-
每个元数据对象约占 150byte,所以如果有 1 千万个小文件,每个文件占用一个 block,则 NameNode 大约需要 2G 空间。如果存储 1 亿个文件,则 NameNode 需要 20G 空间
-
显而易见的解决这个问题的方法就是合并小文件,可以选择在客户端上传时执行 一定的策略先合并,或者是使用 Hadoop 的 CombineFileInputFormat<K,V>实现小 文件的合并
(二)Mapreduce
1、MR中MapTask的工作机制
简单概述:
- inputFile通过split被切割为多个split文件,通过Record按行读取内容给map(自己写的处理逻辑的方法) ,数据被map处理完之后交给OutputCollect收集器,对其结果key进行分区(默认使用的hashPartitioner),然后写入buffer。
- 每个map task 都有一个内存缓冲区(环形缓冲区),存放着map的输出结果,当缓冲区快满的时候需要将缓冲区的数据以一个临时文件的方式溢写到磁盘,当整个map task 结束后再对磁盘中这个maptask产生的所有临时文件做合并,生成最终的正式输出文件,然后等待reduce task的拉取。
详细步骤:
-
读取数据组件 InputFormat (默认 TextInputFormat) 会通过 getSplits 方法对输入目录中的文件进行逻辑切片规划得到 block,有多少个 block就对应启动多少个 MapTask。
-
将输入文件切分为 block 之后,由 RecordReader 对象 (默认是LineRecordReader) 进行读取,以 \n 作为分隔符, 读取一行数据, 返回 <key,value>, Key 表示每行首字符偏移值,Value 表示这一行文本内容。
-
读取 block 返回 <key,value>, 进入用户自己继承的 Mapper 类中,执行用户重写的 map 函数,RecordReader 读取一行这里调用一次。
-
Mapper 逻辑结束之后,将 Mapper 的每条结果通过 context.write 进行collect数据收集。在 collect 中,会先对其进行分区处理,默认使用 HashPartitioner。
-
接下来,会将数据写入内存,内存中这片区域叫做环形缓冲区(默认100M),缓冲区的作用是 批量收集 Mapper 结果,减少磁盘 IO 的影响。我们的 Key/Value 对以及 Partition 的结果都会被写入缓冲区。当然,写入之前,Key 与 Value 值都会被序列化成字节数组。
-
当环形缓冲区的数据达到溢写比列(默认0.8),也就是80M时,溢写线程启动,需要对这 80MB 空间内的 Key 做排序 (Sort)。排序是 MapReduce 模型默认的行为,这里的排序也是对序列化的字节做的排序。
-
合并溢写文件,每次溢写会在磁盘上生成一个临时文件 (写之前判断是否有 Combiner),如果 Mapper 的输出结果真的很大,有多次这样的溢写发生,磁盘上相应的就会有多个临时文件存在。当整个数据处理结束之后开始对磁盘中的临时文件进行 Merge 合并,因为最终的文件只有一个写入磁盘,并且为这个文件提供了一个索引文件,以记录每个reduce对应数据的偏移量。
2、MR中ReduceTask 的工作机制
简单描述:
Reduce 大致分为 copy、sort、reduce 三个阶段,重点在前两个阶段。
- copy 阶段包含一个 eventFetcher 来获取已完成的 map 列表,由 Fetcher 线程去 copy 数据,在此过程中会启动两个 merge 线程,分别为 inMemoryMerger 和 onDiskMerger,分别将内存中的数据 merge 到磁盘和将磁盘中的数据进行 merge。待数据 copy 完成之后,copy 阶段就完成了,开始进行 sort 阶段。
- sort 阶段主要是执行 finalMerge 操作,纯粹的 sort 阶段。
- 完成之后就是 reduce 阶 段,调用用户定义的 reduce 函数进行处理 。
详细步骤:
- Copy 阶段: 简单地拉取数据。Reduce 进程启动一些数据 copy 线程(Fetcher), 通过 HTTP 方式请求 maptask 获取属于自己的文件(map task 的分区会标识每个 map task 属于哪个 reduce task ,默认 reduce task 的标识从 0 开始)。
- Merge 阶段: 这里的 merge 如 map 端的 merge 动作,只是数组中存放的是不 同 map 端 copy 来的数值。Copy 过来的数据会先放入内存缓冲区中,这里的缓冲 区大小要比 map 端的更为灵活。merge 有三种形式:内存到内存;内存到磁盘; 磁盘到磁盘。默认情况下第一种形式不启用。当内存中的数据量到达一定阈值, 就启动内存到磁盘的 merge。与 map 端类似,这也是溢写的过程,这个过程中 如果你设置有 Combiner,也是会启用的,然后在磁盘中生成了众多的溢写文件。 第二种 merge 方式一直在运行,直到没有 map 端的数据时才结束,然后启动第 三种磁盘到磁盘的 merge 方式生成最终的文件。
- 合并排序:把分散的数据合并成一个大的数据后,还会再对合并后的数据排序。
- 对排序后的键值对调用 reduce 方法, 键相等的键值对调用一次 reduce 方法, 每次调用会产生零个或者多个键值对,最后把这些输出的键值对写入到 HDFS 文 件中。
3、MR 中 shuffle 阶段
- shuffle 阶段分为四个步骤:依次为:分区,排序,规约,分组,其中前三个步骤 在 map 阶段完成,最后一个步骤在 reduce 阶段完成。
- shuffle 是 Mapreduce 的核心,它分布在 Mapreduce 的 map 阶段和 reduce 阶段。一般把从 Map 产生输出开始到 Reduce 取得数据作为输入之前的过程称 作 shuffle。
- Collect 阶段: 将 MapTask 的结果输出到默认大小为 100M 的环形缓冲区,保存的 是 key/value,Partition 分区信息等。
- Spill 阶段: 当内存中的数据量达到一定的阀值的时候,就会将数据写入本地磁盘, 在将数据写入磁盘之前需要对数据进行一次排序的操作,如果配置了 combiner,还会将有 相同分区号和 key 的数据进行排序。
- Merge 阶段: 把所有溢出的临时文件进行一次合并操作,以确保一个 MapTask 最终 只产生一个中间数据文件
- Copy 阶段: ReduceTask 启动 Fetcher 线程到已经完成 MapTask 的节点上复制一份 属于自己的数据,这些数据默认会保存在内存的缓冲区中,当内存的缓冲区达到一定的阀值 的时候,就会将数据写到磁盘之上
- Merge 阶段: 在 ReduceTask 远程复制数据的同时,会在后台开启两个线程对内存到 本地的数据文件进行合并操作
- Sort 阶段: 在对数据进行合并的同时,会进行排序操作,由于 MapTask 阶段已经对 数据进行了局部的排序,ReduceTask 只需保证 Copy 的数据的最终整体有效性即可。
- Shuffle 中的缓冲区大小会影响到 mapreduce 程序的执行效率,原则上说,缓冲区越大,
- 磁盘 io 的次数越少,执行速度就越快
- 缓冲区的大小可以通过参数调整, 参数:mapreduce.task.io.sort.mb 默认 100M
4、shuffle 阶段的数据压缩机制
在 shuffle 阶段,可以看到数据通过大量的拷贝,从 map 阶段输出的数据,都要 通过网络拷贝,发送到 reduce 阶段,这一过程中,涉及到大量的网络 IO,如果 数据能够进行压缩,那么数据的发送量就会少得多。
hadoop 当中支持的压缩算法: gzip、bzip2、LZO、LZ4、Snappy,这几种压缩算法综合压缩和解压缩的速率,谷歌的 Snappy 是最优的,一般都选择 Snappy 压缩。
5、在写 MR 时,什么情况下可以使用规约
规约(combiner)是不能够影响任务的运行结果的,局部汇总,适用于求和类, 不适用于求平均值.
如果 reduce 的输入参数类型和输出参数的类型是一样的, 则规约的类可以使用 reduce 类,只需要在驱动类中指明规约的类即可
(三)Yarn
1、YARN的资源调度三种模型
在Yarn中有三种调度器可以选择:FIFO Scheduler ,Capacity Scheduler,Fair Scheduler
Apache版本的hadoop默认使用的是Capacity Scheduler调度方式。CDH版本的默认使用的是Fair Scheduler调度方式
FIFO Scheduler(先来先服务)
FIFO Scheduler把应用按提交的顺序排成一个队列,这是一个先进先出队列,在进行资源分配的时候,先给队列中最头上的应用进行分配资源,待最头上的应用需求满足后再给下一个分配,以此类推。
FIFO Scheduler是最简单也是最容易理解的调度器,也不需要任何配置,但它并不适用于共享集群。大的应用可能会占用所有集群资源,这就导致其它应用被阻塞,比如有个大任务在执行,占用了全部的资源,再提交一个小任务,则此小任务会一直被阻塞。
Capacity Scheduler(能力调度器)
对于Capacity调度器,有一个专门的队列用来运行小任务,但是为小任务专门设置一个队列会预先占用一定的集群资源,这就导致大任务的执行时间会落后于使用FIFO调度器时的时间。
Fair Scheduler(公平调度器)
在Fair调度器中,我们不需要预先占用一定的系统资源,Fair调度器会为所有运行的job动态的调整系统资源。
比如:当第一个大job提交时,只有这一个job在运行,此时它获得了所有集群资源;当第二个小任务提交后,Fair调度器会分配一半资源给这个小任务,让这两个任务公平的共享集群资源。
需要注意的是,在Fair调度器中,从第二个任务提交到获得资源会有一定的延迟,因为它需要等待第一个任务释放占用的Container。小任务执行完成之后也会释放自己占用的资源,大任务又获得了全部的系统资源。最终的效果就是Fair调度器即得到了高的资源利用率又能保证小任务及时完成。
2、yarn 的任务提交流程是怎样的
当 jobclient 向 YARN 提交一个应用程序后,YARN 将分两个阶段运行这个应用程序:
第一阶段是启动 ApplicationMaster;
第二阶段是由 ApplicationMaster 创建应用程 序,为它申请资源,监控运行直到结束。
具体步骤如下:
- 用户向 YARN 提交一个应用程序,并指定 ApplicationMaster 程序、启动 ApplicationMaster 的命令、用户程序。
- RM 为这个应用程序分配第一个 Container,并与之对应的 NM 通讯,要求它在 这个 Container 中启动应用程序 ApplicationMaster。
- ApplicationMaster 向 RM 注册,然后拆分为内部各个子任务,为各个内部任务 申请资源,并监控这些任务的运行,直到结束。
- AM 采用轮询的方式向 RM 申请和领取资源。
- RM 为 AM 分配资源,以 Container 形式返回
- AM 申请到资源后,便与之对应的 NM 通讯,要求 NM 启动任务。
- NodeManager 为任务设置好运行环境,将任务启动命令写到一个脚本中,并 通过运行这个脚本启动任务
- 各个任务向 AM 汇报自己的状态和进度,以便当任务失败时可以重启任务。
- 应用程序完成后,ApplicationMaster 向 ResourceManager 注销并关闭自己
3、yarn 集群的架构和工作原理
YARN 的基本设计思想是将 MapReduce V1 中的 JobTracker 拆分为两个独立的服务:ResourceManager 和 ApplicationMaster。ResourceManager 负责整个系统的资 源管理和分配,ApplicationMaster 负责单个应用程序的的管理。
- ResourceManager: RM 是一个全局的资源管理器,负责整个系统的资源管理和分配,它主要由两个 部分组成:调度器(Scheduler)和应用程序管理器(Application Manager)。 调度器根据容量、队列等限制条件,将系统中的资源分配给正在运行的应用程序, 在保证容量、公平性和服务等级的前提下,优化集群资源利用率,让所有的资源 都被充分利用应用程序管理器负责管理整个系统中的所有的应用程序,包括应用 程序的提交、与调度器协商资源以启动 ApplicationMaster、监控 ApplicationMaster 运行状态并在失败时重启它。
- ApplicationMaster: 用户提交的一个应用程序会对应于一个 ApplicationMaster,它的主要功能有: a.与 RM 调度器协商以获得资源,资源以 Container 表示。 b.将得到的任务进一步分配给内部的任务。 c.与 NM 通信以启动/停止任务。 d.监控所有的内部任务状态,并在任务运行失败的时候重新为任务申请资源以重 启任务。
- nodeManager: NodeManager 是每个节点上的资源和任务管理器,一方面,它会定期地向 RM 汇 报本节点上的资源使用情况和各个 Container 的运行状态;另一方面,他接收并 处理来自 AM 的 Container 启动和停止请求。
- container: Container 是 YARN 中的资源抽象,封装了各种资源。一个应用程序会分配一个 Container,这个应用程序只能使用这个 Container 中描述的资源。 不同于 MapReduceV1 中槽位 slot 的资源封装,Container 是一个动态资源的划分 单位,更能充分利用资源。
二、Zookeeper篇
1、Zookeeper监听器原理
- 首先要有一个main() 线程
- 在main() 线程中创建 Zookeeper客户端,这是会创建两个线程,一个负责网络连接通信(Connect),一个负责监听(listener)。
- 通过connect 线程将注册的 监听事件发送给zookeeper。
- zookeeper 的注册监听器列表中将注册的监听事件添加到列表中。
- Zookeeper监听到有数据或者路径发生变化,就将消息发送给 listener线程。
- listener线程内部调用了process() 线程。
2、 ZooKeeper工作机制
- 高可用的分布式数据管理和协调框架,并且能够很好的保证分布式环境中数据的一致性。
- ZooKeeper负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生变化,ZooKeeper就将负责通知已经在 ZooKeeper上注册的观察者做出相应的反应。
- ZooKeeper = 文件系统+通知机制
- 应用场景:统一命名服务,统一配置管理,统一集群管理,服务器节点动态上下线,软负载均衡等等
3、ZooKeeper特点
- ZooKeeper:一个领导者(Leader),多个跟随者(Follow)
- 集群中只要有半数以上的节点存活,ZooKeeper集群就能正常服务
- 全局数据一致,每个Server(所有的节点都是一个 server)保存一份相同的数据副本,客户端无论连接到哪一个Server,数据都是一致的
- 更新请求顺序进行,来自同一个客户端的更新请求按其发送顺序依次进行
- 数据更新原子性,依次数据更新要么成功,要么失败
- 实时性,在一定时间范围内,客户端能读到最新数据
4、Zookeeper 有哪些节点?临时节点永久节点用来做什么?
- Zookeeper的数据模型可以看做是一棵树,每个节点称作一个Znode,每个Znode默认能够存储1MB的数据,每个Znode都可以通过其路径唯一标识
- 持久化目录节点:客户端与Zookeeper断开连接后,该节点依然存在
- 持久化顺序节点:客户端与Zookeeper断开连接后,该节点依然存在,只是zookeeper给该节点名称进行顺序编号
- 临时目录节点:客户端与Zookeeper断开连接后,该节点被删除
- 临时顺序节点:客户端与Zookeeper断开连接后,该节点被删除,只是zookeeper给该节点名称进行顺序编号
5、Zookeeper 的ZAB选举算法
- 半数机制:集群中半数以上机器存活,集群可用。所以Zookeeper适合安装奇数台服务器。
- Zookeeper虽然在配置文件中并没有指定Master和Slave。但是,Zookeeper工作时,是有一个节点为Leader,其他则为Follower,Leader是通过内部的选举机制临时产生的。
以一个简单的例子来说明整个选举的过程
假设有五台服务器组成的Zookeeper集群,它们的id从1-5,同时它们都是最新启动的,也就是没有历史数据,在存放数据量这一点上,都是一样的。假设这些服务器依序启动,来看看会发生什么。
1) Zookeeper的选举机制
- 服务器1启动,此时只有它一台服务器启动了,它发出去的报文没有任何响应,所以它的选举状态一直是LOOKING状态。
- 服务器2启动,它与最开始启动的服务器1进行通信,互相交换自己的选举结果,由于两者都没有历史数据,所以id值较大的服务器2胜出,但是由于没有达到超过半数以上的服务器都同意选举它(这个例子中的半数以上是3),所以服务器1、2还是继续保持LOOKING状态。
- 服务器3启动,根据前面的理论分析,服务器3成为服务器1、2、3中的老大,而与上面不同的是,此时有三台服务器选举了它,所以它成为了这次选举的Leader。
- 服务器4启动,根据前面的分析,理论上服务器4应该是服务器1、2、3、4中最大的,但是由于前面已经有半数以上的服务器选举了服务器3,所以它只能是Follower。
- 服务器5启动,同4一样是Follower。
6、Zookeeper监听器原理
- 首先要有一个main() 线程
- 在main() 线程中创建 Zookeeper客户端,这是会创建两个线程,一个负责网络连接通信(Connect),一个负责监听(listener)。
- 通过connect 线程将注册的 监听事件发送给zookeeper。
- 在zookeeper 的注册监听器列表中将注册的监听事件添加到列表中。
- Zookeeper监听到有数据或者路径发生变化,就将消息发送给 listener线程。
- listener线程内部调用了process() 线程。
7、 Zookeeper的部署方式有哪几种?集群中有哪些角色?最少需要多少台机器?
- 部署方式单机模式、集群模式
- 角色:Leader和Follower
- 集群最少需要机器数:3
8、 Zookeeper 客户端命令行
命令基本语法 | 功能描述 |
---|---|
help | 显示所有操作命令 |
ls path [watch] | 使用 ls 命令来查看当前znode中所包含的内容 |
ls2 path [watch] | 查看当前节点数据并能看到更新次数等数据 |
create | 普通创建 |
-s | 含有序列 |
-e | 临时(重启或者超时消失) |
get path [watch] | 获得节点的值 |
set | 设置节点的具体值 |
stat | 查看节点状态 |
delete | 删除节点 |
rmr | 递归删除节点 |
history | 显示历史命令 |
setAcl path acl | 设置ACL权限 |
getAcl path | 获取ACL 权限 |
close | 关闭连接 |
quit | 退出 |