你问我答1 - HDFS数据的写入原理

时间:2022-12-11 21:55:43

我们在集群中配置了hdfs异构存储策略,配置如下:


dfs.datanode.data.dir:/data02/dfs/dn,/data03/dfs/dn,[ARCHIVE]/mnt/nfs01/dfs/dn


dfs.namenode.replication.min:1


dfs.replication:2


然后做了如下测试:


hdfs dfs -mkdir /user/xxx/warm


hdfs storagepolicies -setStoragePolicy -path /user/xxx/warm -policy warm


hdfs mover -p /user/xxx/warm


hadoop jar hadoop-mapreduce-client-jobclient-3.0.0-cdh6.3.2-tests.jar  TestDFSIO -Dmapreduce.job.queuename=q1 -write -nrFiles 100 -fileSize 10240


以上脚本写100个10G的文件到/user/xxx/warm,平均耗时1147.63s


hdfs dfs -mkdir /user/xxx/hot


hdfs storagepolicies -setStoragePolicy -path /user/xxx/hot -policy hot


hdfs mover -p /user/xxx/hot


hadoop jar hadoop-mapreduce-client-jobclient-3.0.0-cdh6.3.2-tests.jar  TestDFSIO -Dmapreduce.job.queuename=q1 -write -nrFiles 100 -fileSize 10240


以上脚本写100个10G的文件到/user/xxx/hot,平均耗时379.3s


根据我们配置的dfs.namenode.replication.min:1,dfs.replication:2和副本放置规则,无论存储策略为warm还是hot,第一份副本都放置在本节点的disk上,另一个副本异步放置到disk或archive上


所以以上两个脚本预期的耗时应该是一样的,但是实际不符合预期,请问原因何在?




你的问题就是期望假如数据放到了archive,就希望这个数据的所有副本,比如3个副本都放到archive的主机或者磁盘上是吧?跟描述里说的性能数据,比如花了多少秒是没关系的。




有关系,根据官网的说法,三副本中第一个副本放到disk,其余副本异步放到archive,因此warm策略性能应该是和hot没有差别的。但实际差别很大,dfs.namenode.replication.min=1,第一个副本写成功后,其余副本异步写到archive或者disk




所以你应该关心2个问题:1.配置了异构磁盘的HDFS的分层存储后,block的分布是否符合预期;2.对于写入到hot或者warm目录的性能是否符合预期,目前看到的数据理论应该性能差不了太多,但是实际差别很大。




第一个问题我们自己看过日志,block分布符合预期,一个在disk上,两个在archive上。第二个问题就是我们关心的问题




第二个问题不应该关心才对啊,因为是挂载的NAS盘到所有DN,真的在有数据写入的时候,会有IO争用的问题,所以会慢。




性能问题需要关心呀,异步写到nfs盘不应该影响性能呀,这与理论不符




就是认为HDFS写入数据是异步的,1个block写入成功了,namenode就返回client成功,其余两个会异步在后台慢慢做,这个场景他们认为第3个副本是异步写到NFS,不应该影响到写入时间才对。




我再描述一下问题哈,warm策略的时候,写文件第一个block块写入本节点的disk,另外两个block异步写入archive,hot策略的时候,第一个block块写入本节点disk,另外两个异步写入其他节点disk,所以无论是warm还是hot写数据的耗时都是第一个block块写入本地disk的时间,应该性能是一样的,但实际warm耗时远多于hot,想知道原因和解决方法。或者我们对hdfs写数据原理理解有误差




你问我答1 - HDFS数据的写入原理

HDFS写数据要所有block都写成功了才返回给client写成功,这里默认3副本,从这个图 444 / 555 ack,即写到3个DN都成功了才ack返回成功。你之前写2个副本只到2个DN的时候,同理。




dfs.namenode.replication.min=1具体含义是什么呢?我理解的是写数据时,满足一个副本即返回成功,其他副本异步完成直至满足dfs.replication。


另外还有类似参数dfs.replication.max的含义?




dfs.namenode.replication.min和dfs.namenode.replication.max这两个参数和之前说的默认block包含其副本都写入成功了才返回给客户端不矛盾。


“dfs.namenode.replication.min : Minimal block replication.


Once dfs.namenode.replication.min has been met, write operation will be treated as successful.


But this replication up to dfs.replication will happen in sequential pipeline. First Datanode writes the block and forward it to second Datanode. Second Datanode writes the block and forward it to third Datanode”


1.dfs.namenode.replication.min是说假如在数据写入时候,有DataNode损坏(比如某个block的第2个和第3个副本写到第2台和第3台DataNode失败),某个block只要达到了dfs.namenode.replication.min即表明数据写入成功,剩余的dfs.replication - dfs.replication.min个副本会异步的在后端去复制副本数。


参考(重点看回复):

​https://*.com/questions/23799658/hadoop-replication-factor-confusion​

​https://*.com/questions/37533600/whats-the-hdfs-writing-consistency​


2.dfs.namenode.replication.max是block的最大副本数,设置后,用户在操作数据写入的时候不能指定超过这个副本数。


参考(重点看回复):

​https://*.com/questions/71265410/what-is-the-meaning-of-dfs-replication-max​




总结就是跟之前的不冲突。正常情况是等所有的副本都写入成功才返回client,如果出现异常比如DN损坏,则按照min默认是1个副本写入就算成功,剩下的副本数异步再去做。




HDFS数据的写入可以认为又同步又异步,集群一切正常就是同步,如果有部分DN或者磁盘故障,即集群有异常时,数据写入可以认为又是异步的,只要达到dfs.replication.min就行