本文是基于石杉码农公众号关于HDFS的4篇文章作得总结梳理,因为微信公众好跳转连接会过时,就不放上来了,有兴趣的能够直接前往公众号查看《2018年原创汇总》文章查找。微信
Active NameNode-主节点:对外提供服务接收请求。网络
Standby NameNode-备节点:一是接收和同步主节点的edits log以及执行按期checkpoint,二是在Active NameNode的时候进行主备切换。架构
存放NameNode元数据写入的editLogs,供Standby NameNode拉取,主要意义是保持Active NameNode和Standby NameNode的同步,但必须高可用,因此是集群部署。并发
存放真实数据的节点异步
一份数据会分为多个block存放在各个DataNode上,一个block会创建副本,放入其余的DataNode,保证一个block有三个副本在不一样的DataNode上.优化
由于在Active NameNode向JournalNode发送editLog的时候,必须保证顺序。因此须要获取transacationId来维护这个顺序,这也意味着transacationId的获取不能并发。线程
主要是运用了double-buffer双缓冲机制,什么是双缓冲勒。要发送的editLog数据是先放在缓冲区里面,而后再由某个线程统一发送到JournalNode,提升网络写的效率。但这里有个问题得解决,如何让在网络写的过程当中不影响数据写入缓冲区勒?只能引入双缓冲机制,即将缓冲区域分为两份,一份用于存放即时写入的数据,另外一份用于存放将要被网络写的数据,当须要网络写的时候将两个区域切换,这样两个操做才能互相不影响。日志
上图第一次获取锁是为了生成transacationId,第二次获取锁的操做就是优化网络写,保证每一个请求nameNode的线程不作无效的写入请求。这里保留一个疑问。第二次获取锁应该是非公平锁把,理论上最后一个transacationId的线程获取到锁效率会更高一些,HDFS没有对这里作优化吗?文章里没有提到这里更细的解释,这里暂时存疑。blog
若是使用传统的IO传输,将会产生频繁的网络传输,效率很低。队列
加快磁盘写入内存效率,默认是512Byte。
进一步缓冲要发送网络的数据,默认64M。
注:这里是异步的,意思是往OutPutStream写入数据的同时,也在DataStreamer线程也在发送数据包。
为了保证同一时间只能有一个客户端获取NameNode上面一个文件的契约,而后才能够写入数据。在写文件的过程期间,客户端须要开启一个线程,不停的发送请求给NameNode进行文件续约。
NameNode若是每次都遍历NameNode去淘汰过时的契约,效率是很是低下的,这里的优化就是对每一个契约按最近一次续约时间进行排,序每次都把续约时间最老的契约排在最前头。当每次检查是否过时时,从头开始遍历,只要遍历到没有过时的就不遍历了,由于后面的一定没有过时。相似的,运用这种方式优化的案例还有eureka维护服务实例心跳续约使用的机制。