如何比较装X地回答问题 | 面试系列.1

时间:2019-08-29
本文章向大家介绍如何比较装X地回答问题 | 面试系列.1,主要包括如何比较装X地回答问题 | 面试系列.1使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

公众号后台比较多同学让我写面试相关的文章,在之前的文章 从面试官的角度谈谈大数据面试 也聊了很多,但是有同学吐槽说我没有把答案写上去,当时我的心里是拒绝写的,这有啥好写的,又不难,Google一大堆。但是呢,吐槽的人多了我也就妥协了,这次我不仅把答案加上去了,还会加很多的分析和建议。

之前也和大家说过,由于市场所需,行业红利,金钱诱惑,朋友下套...等等原因(瞎说的瞎说的),我的面试和被面试经验都还是比较丰富的,可以帮助大家剖析下面试官的心理,怎么能说出面试官比较喜欢的答案。说实话,面试的时候其实面试官可能会比你还希望你能进来这家公司,只要你能戳到面试官的那个“点”,那你就有戏。

以下
黑色字体是正经回答
引用是我小声BB

hdfs 的数据读写过程 ?

这是一个很普通的问题,我也很喜欢问这个问题,但是我的目的也不仅仅是考察你懂不懂这个,因为这个问题要答出来并不难,很多人可能接触hadoop的第一天就知道了,无非就是从namenode获取block元信息,pipline写datanode,啪啦啪啦,很平常的一顿操作,很稳,也没什么出彩的。但是其实呢,你也可以回答得“装逼”一点,可能会让昏昏欲睡的面试官耳目一新,对你稍微有点刮目相看,印象也会稍微深刻一点,“这小子装逼装得还挺像样的...”。

下面我要开始了。

“读写的过程我稍微看过一下源码,我先说下写的过程,写会稍复杂些我可以讲得详细一点:

  1. 首先client创建一个OutputStream输出流,在此过程中client通过rpc向namenode添加一个文件记录,得到该文件的租约,启动一个 DataStreamer 线程,线程中会维护 dataQueue和ackQueue队列。

  2. FSDataOutputStream 输出流建好之后,就可以调用 write 方法进行数据的写入。在写入过程中先将数据写入client本地的缓存中,此缓存默认是9个chunk(512B)的大小,当本地缓存写满之后 (如果要写入的数据长度大于本地缓存的长度,则直接将缓存长度的数据写入currentPacket中) ,计算这些数据的checksum,并写入currentPacket中,currentPacket写满之后放入dataQueue中排队并通知DataStreamer线程去dataQueue中消费数据。(数据先写入本地buf,然后写入packet,等packet(64k)满之后才向namenode申请blockId)

  3. DataStreamer线程从dataQueue中取出packet,如果DataStreamer的stage为PIPELINE_SETUP_CREATE时,表示当前block的pipeline还没有建立,向namenode申请blockId和block的locations,将申请到的locations组成一个pipeline,与第一个dn建立socket连接,由Sender发送写请求。

  4. 新启动ResponseProcessor线程接收dn返回的packet ack,并更新DataStreamer的stage,由PIPELINE_SETUP_CREATE变为DATA_STREAMING 将要发送的packet从dataQueue中移到ackQueue中,然后向pipeline中发送packet。

其实把client端的操作说完这个写过程基本就可以了,当然如果你想更好一点可以看情况挑一些datanode端的内容来说,或者你可以画个图,边画边说显得更自然一点。

  1. datanode端在client创建pipeline时,通过DataXceiverServer接收到client的socket请求,创建一个DataXceiver线程,由DataXceiver线程处理来自client的写请求;

  2. DataXceiver线程会实例化一个BlockReceiver对象,并判断是否有downstream,如果有则创建一个downstream的socket,发送写请求;

  3. 与downstream建立连接之后,在blockReceiver.receiveBlock循环调用receivePacket接收packet,向downstream发送packet之前将packet放入ackQueue(当前ackQueue是PacketResponder线程维护的)中,然后将data和checksum写入磁盘;

  4. 在blockReceiver.receiveBlock中还会启动一个PacketResponder线程,此线程负责接收downstream发送的packet ack,校验成功之后从ackQueue中移除,向upstream发送自己的ack和downstream的ack;

  5. 最终所有的ack都汇集到 ResponseProcessor 线程中,如果ack没有error则从ackQueue中移除;如果有error,先将ackQueue中的packet移到dataQueue中,然后将发生error的dn从pipeline中删除,从namenode中重新申请dn与原有的没有发生error的dn组成新的pipeline,在addDatanode2ExistingPipeline中判断是否要transfer已经发送的packet,将已经发送成功的packet从之前正常的dn上transfer到新增加的dn上,并更新block是stamp,这样发生故障的DataNode节点上的block数据会在节点恢复正常后被删除。

其实讲到这里已经是超额完成任务了,真实面试的过程中不需要像我上面说得那么复杂和准确,可以直接复述我上面的内容,适当地说几个类名来,读的过程就不需要再说得那么详细,不然可能会适得其反,让面试官听得有点不耐烦,所以可以尽量简洁一些。

1、跟namenode通信查询元数据,找到文件块所在的datanode服务器
2、挑选一台datanode(就近原则,然后随机)服务器,请求建立socket流
3、datanode开始发送数据(从磁盘里面读取数据放入流,以packet为单位来做校验)
4、客户端以packet为单位接收,先在本地缓存,然后写入目标文件

当然为了避免翻车,还是希望大家可以真的去看看部分源码,装X要适当,稍微秀一下就可以,不然被追问导致翻车的可能性还是有的。

hdfs 有哪些进程,各自的作用是什么?

NameNode:Namenode 管理者文件系统的Namespace。它维护着文件的元数据,包括文件名、副本数、文件的BlockId,以及block所在的服务器,会接受来自client端的读写请求,和datanode的block信息上报。

DataNode:hfds的工作节点,他们根据客户端或者是namenode的调度存储和检索数据,并且定期向namenode发送他们所存储的块(block)的列表。

JournalNode:负责两个NameNode高可用时的数据同步保证数据一致,存放NameNode的editlog文件(元数据),部署在任意节点,奇数个。

DFSZKFailoverController(ZKFC):负责监控NameNode的健康状态,并及时把信息状态写入Zookeeper,如有异常会触发主从切换,部署在有NameNode的节点。

另外你上百度搜这个问题的话,很少会提到后面两个进程,SecondaryNameNode却经常被提到,这个东东其实可以不用说,是 hadoop 比较旧而且已经基本没公司用的一种部署方式,NameNode会有单点问题,所以可以不用和其他的混合在一起说。

hdfs 如何保证可用性 ?

NameNode的高可用由JournalNode和DFSZKFailoverController保证,JN负责主从数据的一致,ZKFC负责主从的failover;

数据在HDFS中是默认存储三份的,且在不同的DataNode,所以DataNode挂掉两台仍然能保证数据的完整性;(挂三台的概率理论上是很低的,真挂了的话就算是重大事故了,等着罚钱吧。那有什么更好的解决办法呢?其实是有的,就是逢年过节记得要拜拜服务器,多上几柱香)

JournalNode也是分布式的,因为有选举机制,所以默认要大于1的奇数个服务器在线,挂掉一两台问题也不太大,但是要做好监控。

DFSZKFailoverController(ZKFC)这个进程貌似在设计上并没有去关注可用性的问题,它是部署在两个NameNode节点上的独立的进程,但是其实他的作用就是辅助zookeeper做NameNode的健康监控,所以可以直接说Zookeeper的可用性。
Zookeeper是一个独立的分布式系统,用于管理和协调分布式系统的工作,它本身也会通过zab协议来保证数据一致,和主备节点的选举切换等等。

另外,这个类型的文章我也准备来写一个系列,每一篇会涉及几个大数据面试的问题和答案,也会有我的一些想法和建议。这是开篇,就先写HDFS相关的,另外我会尽量提高发文的频率,大家还是多多支持啦,好看就点个在看吧。

觉得有价值请关注 ▼

原文地址:https://www.cnblogs.com/uncledata/p/11427989.html