《Hadoop权威指南:大数据的存储与分析》—3.6.2 剖析文件写入
3.6.2 剖析文件写入
接下来我们看看文件是如何写入HDFS 的。尽管比较详细,但对于理解数据流还是很有用的,因为它清楚地说明了HDFS 的一致模型。
我们要考虑的情况是如何新建一个文件,把数据写入该文件,最后关闭该文件。如图3-4所示。
客户端通过对DistributedFileSystem对象调用create()来新建文件(图3-4中的步骤1)。DistributedFileSystem对namenode创建一个RPC调用,在文件系统的命名空间中新建一个文件,此时该文件中还没有相应的数据块(步骤2)。namenode执行各种不同的检查以确保这个文件不存在以及客户端有新建该文件的权限。如果这些检查均通过,namenode就会为创建新文件记录一条记录;否则,文件创建失败并向客户端抛出一个IOException异常。DistributedFileSystem向客户端返回一个FSDataOutputStream对象,由此客户端可以开始写入数据。就像读取事件一样,FSDataOutputStream封装一个DFSoutPutstream对象,该对象负责处理datanode和namenode之间的通信。
图3-4. 客户端将数据写入HDFS
在客户端写入数据时(步骤3),DFSOutputStream将它分成一个个的数据包,并写入内部队列,称为“数据队列”(data queue)。DataStreamer处理数据队列,它的责任是挑选出适合存储数据复本的一组datanode,并据此来要求namenode分配新的数据块。这一组datanode构成一个管线——我们假设复本数为3,所以管线中有3个节点。DataStreamer将数据包流式传输到管线中第1个datanode,该datanode存储数据包并将它发送到管线中的第2个datanode。同样,第2个datanode存储该数据包并且发送给管线中的第3个(也是最后一个)datanode (步骤4)。
DFSOutputStream也维护着一个内部数据包队列来等待datanode的收到确认回执,称为“确认队列”(ack queue)。收到管道中所有datanode确认信息后,该数据包才会从确认队列删除(步骤5)。
如果任何datanode在数据写入期间发生故障,则执行以下操作(对写入数据的客户端是透明的)。首先关闭管线,确认把队列中的所有数据包都添加回数据队列的最前端,以确保故障节点下游的datanode不会漏掉任何一个数据包。为存储在另一正常datanode的当前数据块指定一个新的标识,并将该标识传送给namenode,以便故障datanode在恢复后可以删除存储的部分数据块。从管线中删除故障datanode,基于两个正常datanode构建一条新管线。余下的数据块写入管线中正常的datanode。namenode注意到块复本量不足时,会在另一个节点上创建一个新的复本。后续的数据块继续正常接受处理。
在一个块被写入期间可能会有多个datanode同时发生故障,但非常少见。只要写入了dfs.namenode.replication.min的复本数(默认为1),写操作就会成功,并且这个块可以在集群中异步复制,直到达到其目标复本数(dfs.replication的默认值为3)。
客户端完成数据的写入后,对数据流调用close()方法(步骤6)。该操作将剩余的所有数据包写入datanode管线,并在联系到namenode告知其文件写入完成之前,等待确认(步骤7)。namenode已经知道文件由哪些块组成(因为Datastreamer请求分配数据块),所以它在返回成功前只需要等待数据块进行最小量的复制。
复本怎么放
namenode如何选择在哪个datanode存储复本(replica)?这里需要对可靠性、写入带宽和读取带宽进行权衡。例如,把所有复本都存储在一个节点损失的写入带宽最小(因为复制管线都是在同一节点上运行),但这并不提供真实的冗余(如果节点发生故障,那么该块中的数据会丢失)。同时,同一机架上服务器间的读取带宽是很高的。另一个极端,把复本放在不同的数据中心可以最大限度地提高冗余,但带宽的损耗非常大。即使在同一数据中心(到目前为止,所有Hadoop 集群均运行在同一数据中心内),也有多种可能的数据布局策略。
Hadoop 的默认布局策略是在运行客户端的节点上放第1个复本 (如果客户端运行在集群之外,就随机选择一个节点,不过系统会避免挑选那些存储太满或太忙的节点)。第2个复本放在与第一个不同且随机另外选择的机架中节点上(离架)。第3个复本与第2个复本放在同一个机架上,且随机选择另一个节点。其他复本放在集群中随机选择的节点上,不过系统会尽量避免在同一个的机架上放太多复本。
一旦选定复本的放置位置,就根据网络拓扑创建一个管线。如果复本数为3,则有图3-5所示的管线。
图3-5. 一个典型的复本管线
总的来说,这一方法不仅提供很好的稳定性(数据块存储在两个机架中)并实现很好的负载均衡,包括写入带宽(写入操作只需要遍历一个交换机)、读取性能(可以从两个机架中选择读取)和集群中块的均匀分布(客户端只在本地机架上写入一个块)。
- 点赞
- 收藏
- 关注作者
评论(0)