如上是顺利完成,如果在客户端获取到一个新申请的数据块时,无法建立连接,会调用abandonBlock()方法放弃喝个数据块,客户端会再次通过addBlock()方法获取新的数据块。
在客户端写某个数据块时,如果副本节点出了错误,客户端会调用getAdditionalDatanode()方法向Namenode申请一个新的datanode来替代故障datanode。然后客户端调用updateBlockForPipeline()方法向Namenode申请为这个数据块分配新的时间戳,这样故障节点的数据块的时间戳就会过期,回本删除,最后客户端就可以使用新的时间戳建立新的数据管道流近些写数据了。
如果在写的过程中客户端发生了故障,为了防止故障,对于任意的一个client打开的文件都需要client定期调用clientProtocol.renewLease()方法更新租约,如果Namenode长时间没有收到client的租约更新信息,就会认为client故障,触发一次租约恢复操作,关闭文件并且同步所有数据节点上这个文件数据块的状态,确保hdfs系统中这个文件正确且保持一致。
如果在写数据的过程中Namenode发生故障呢,则需要HA发挥作用了。
2、ClientDatanodeProtocol
客户端与datanode间的接口,主要用户客户端获取datanode节点信息是调用,真正的读写是通过流式接口进行的。其中主要定义两部分,一部分是支持HDFS文件读写的操作,例如调用getReplicaVisibleLength()获取datanode节点某个数据块的真实数据长度和getBlockLocalPathInfo()方法等,另一部分是支持DFSAdmin中与datanode节点管理相关的命令。
3、DatanodeProtocol
datanode与namenode间的通信接口,包括namenode通过该接口中的方法返回向datanode下发指令。datanode则是通过该接口向namenode进行注册,汇报块信息和缓存信息。DataNode使用这个接口与Namenode握手、注册、发送心跳、进行全量以及增量的数据块汇报,NameNode会在Datanode的心跳响应中携带Namenode的指令。该接口主要的方法分为三种类型,Datanode的启动相关,心跳相关,数据块的读写相关。
(Datanode启动相关)Datanode启动会与NameNode进行4次交互,通过versionRequest()与NameNode进行握手操作,然后调用refisterDatanode()向NameNode注册当前的datanode,接着调用blockReport()汇报datanode上存储的所有数据块信息,最后调用cacheReport()汇报datanode缓存的所有数据块。
握手主要是返回namenode的一些命名空间ID,集群ID,hdfs的版本号等,datanode收到信息后进行校验对比,判断是否能够与该namenode协同工作,能否注册。
块汇报后会根据datanode上报数据块存储情况建立数据块与datanode节点的对应关系。blockReport()在启动的时候和指定时间间隔的情况下发生。cacheReport()和blockReport()方法完全一致。只不过是汇报当前datanode上的缓存的所有数据块。
(心跳相关)datanode会定期的向namenode发送心跳(dfs.heartbeat.interval=3s),如果namenode很长时间没有收到datanode的心跳信息,则认为该datanode失效。每次心跳都会包含datanode节点上的存储的状态,缓存状态,正在写文件数据的连接数,读写数据使用的线程等。在开启了HA的状态下,datanode需要向两个namenode同时发送心跳信息,不过只有active才会向datanode发送指令。
(数据块读写相关)datanode会向namenode汇报损坏的数据块,以及定期性namenode汇报datanode新接手的数据块或者删除的数据块。
4、InterDatanodeProtocol
datanode和datanode间的接口,主要用于数据块的恢复操作,以及同步datanode节点上存储数据块副本的信息。主要用于租约恢复操作。
客户端打开一个文件进行操作时,首先要获取这个文件的租约,并且还需要定期更新这个租约,不然,namenode则会认为该client异常,namenode就会触发租约恢复操作(同步数据管道中所有datanode上该文件数据库的状态,并强制关闭这个文件)。
租约恢复不是由namenode控制的负责的,而是namenode在数据管道中选择出一个datanode的恢复主节点,然后下发恢复指令触发这个数据节点控制租约恢复操作,也就是有这个恢复主节点协调整个租约恢复操作的的过程。租约恢复操作就是将数据管道中所有的datanode节点保存同一的数据块状态(时间戳和数据块长度)同步一致。
5、NamenodePortocol
主要用于namenode的ha机制,或者单节点的情况下是secondaryNamenode也namenode之间的通信接口
2.2、流式接口