一:为什么学习hdfs?
- 在没有hdfs之前,我们存储数据,将数据存放在硬盘中。
这样有个问题,如果硬盘坏了怎么办?我们数据将会丢失。
另外如果数据量非常大,我们的读写效率怎么保证。
以上俩个大的问题,是我们作为存储数据要思考的非常关键的俩个点。
二:hdfs是什么?
1.0 版本
DataNode
- 分布式(解决IO瓶颈)
采用分布式方式进行存储。将我们的相连的数据,按照一定的规定进行切割放在不同的存储器中,才访问的时候,我们从不同的存储器中取出来,之后进行拼接,得到我们的最终结果,这种分布式的方式大大提高了查询的效率。 - 高可用(解决单点故障)
将我们的数据进行复制备份,存放在多个存储器中,这样及时一个出现问题,那么其他的依旧可以使用。
此图说明了在存储器(datanodes)的数据存储架构。采用了了高可用和分布式的结构。
NameNode
- 为什么出现NameNode?
因为我们的DataNode大多了,在真实环境中,我们的DataNode是非常多的,每次client进行访问的时候,寻找对应的地址都是非常苦难的 - NameNode是什么?
因为上述原因,我们在建立了一个NameNode。他的主要作用就是管理我们的DataNode。当client进行传输数据和读取数据的时候,先要通过NameNode进行查询,得到具体的位置,之后进行操作。包括监控每个DataNode是否宕机,这些都是NameNode的作用。 - NameNode怎么使用?
NameNode管理大量的DataNode,而且会进行频繁的IO。所以,在NameNOde中,我们会将数据存储在内存中,在重启的时候会存放在硬盘中,下次在打开在进行加载。
Secondary NameNode
- 为什么出现Secondary NameNode?
随着NameNode的管理数据越来越多,内存会变得非常大,如果出现不正常的关机,例如宕机这种情况,会将我们的的内存中大量的数据全部都丢失,后期恢复非常麻烦。 - 什么是Secondary Namenode?
对NameNode进行备份和维护。 - 怎么使用?
- 方法一:进行快照。
定期将NameNode的数据进行拍快照进行处理。- 优点:恢复快。
- 缺点:每次拍照有间隔,这样恢复的时候会丢失一些数据。
- 方法二:进行写日志。
将NameNode的每个操作步骤进行记录,当需要的时候,直接将记录重新加载。- 优点:不会造成数据的丢失。
- 缺点:随着时间的推移,后期恢复工作量非常大,非常浪费时间。
- 方法三:进行快照加日志的结合。
我们定期将数据快照,之后在每个快照的中间,将数据进行写日志。
这个样子,我们就可以保证数据不会丢失,另外数据恢复也非常快。
- 方法一:进行快照。
2.0 版本
1. 为社么出现2.0?
在1.0中,我们对于DataNode进行了高可用,但是对于NameNode和SecondaryNameNode并没有进行高可用管理。
2. 新版本有什么改变?
JournalNode
- 我们对于SecondaryNameNode进行了多个进行部署,并且存储在硬盘上。
NameNode
- ActiveNN 主节点。
- StandyNN 备用节点。
ZKFC
- 为什么出现?
我们对于NameNode进行了高可用。但是我们需要对NameNode进行监控。所以,出现了ZKFC。
zookeeper
- 如果其中一个NameNode宕机了,我们需要进行选举,选出一个来进行充当leader。
注意问题
- 脑裂
- 为什么出现脑裂?
脑裂是指,我们的ANN和ZKFC都进行裆机了,这个时候,启动备用节点当主要节点,结果过了一会,坏的节点好了,这个时候都进行传输命令,这个时候,客户端不知道该听谁的 - 怎么做?
- 只要保证在同一时刻,Cilent只能接受到一个NN的命令。
- 对于刚好的那个机器,先和他谈,如果他愿意当备用,那直接变成备用,如果不愿意,直接杀死他的进程。
- 为什么出现脑裂?
3.0 版本
1. 为什么出现3.0版本?
- 每个文件都进行三个备份,很多时候一些使用少的文件,没有必要备份那么多,所以,我们可以进行优化。
- 对于有些DataNode存储数据量不一样,有些使用率非常高,有些使用率比较低,这个对于资源的消耗也是非常大的。
2. 怎么实现?
- 可擦除编码。
- 均衡处理数据
例如我们刚刚添加了一个硬盘,在之前的硬盘数据比较多,现在新的没有数据,这个时候,会自动的将数据进行做调整
三:hdfs怎么使用?
宏观读写流程
- 客户端向hdfs发送写数据请求。
- filesystem向=通过rpc调用NameNode的create方法。
NN先检查是否有足够的空间存储数据,另外这个路劲上是否有数据。
有足够空间,创建一个空的对象,并返回一个成功的状态。
没有足够空间,直接抛出异常,给客户端显示错误的信息。 - HDFS接受到成功的转台,会创建一个对象FSDateOutputStream的对象给客户端使用。
- 客户端向NameNode咨询第一个存放的位置。
通过机架感知策略(node1,node3,node8) - 需要将客户端和DataNode创建连接。
pipeline(管道)
客户端和node1相连。
nodo1和node3相连。
node3和node8相连。 - 客户端将文件按照block进行切分数据,但是按照packet发发送数据。
默认一个packet大小为64k。一个block为128M,一个block为2048个packet。 - 客户端使用FSDateOutputStream的对象将数据输出。
客户端先将第一个packet发送给node1.并赋予node1一个ack状体。
node1接收到数据之后会向node3发送数据,并赋予node3一个ack状态。
node3接受到数据之后回向node8发送数据,并赋予node8一个ack状态。
node8接受完这个packet之后会向node3返回true。
node3接受完这个packet之后会向node1返回一个true。
node1接受完这个packet之后会向client发送true。 - 客户端接收到true之后说明这个packet发送完成,直到所有的packet全部都发送完成。
- 客户端完成之后会向NameNode传输true。
- 之后询问下一个packet的传输位置, 直到所有的全部传输完毕,管道就会被撤销。
- 当所有的信息都被传输完成之后,NameNode会存储所有的文件与Block和NameNode的存储关系。
微观读写流程
- 我们将硬盘中的数据写入buffered中。
- 之后buffer中的数据按照512B为一个chunk(块)在加上checksum校验值存放,满了之后放在packet(包)中,本来一个packet能放128个chunk,但是加了一个checknum所以只能放127个。
4. 当packet满了的时候,存入dataqueue消息队列。
5. 之后数据经过dataQueue中,打他Queue的作用1:从Dataqueue中取出数据。2:存在ackQueue中。3:将数据放在管道中
6. 之后数据在管道中进行传递。
7.如果数据在传输过程中发生失误。返回消息给ResponseProcessor中,将之前的数据重新放回到DataQueue中。
8. 如果数据没问题,那么返回成功值给ResponseProcessor将存在ackQueue中的数据进行杀死。