シリーズ概要: Hadoop3.1.1システムアーキテクチャ-など詳細なグラフィックスとクライアントのソースを設定し、設計の原則:概要
そして、前: Hadoop3.1.1ソースクライアントのコメント:書き込みは、通話を確立し、準備ができ-RPCをストリーム
メインキャリアはデータの書き込みを与えるために3
キャリア1は、当社の実際のデータ、バイトの一般的配列にHDFSに書き込まれます
2バイトのベクトル配列、オブジェクトのクラスのチェックサム計算におけるバイトアレイであるFSOutputSummer
図3は、キャリア2からの重要なキャリアおよびキャリアデータノードのクライアント通信データ(実データ3)がキャリア2及びヘッダチェックサムから結合され、パケットは、標識された、及び完全又はパケットであります
dataQueueで埋めDataStreamerデーモンスレッドのメッセージキューに圧入された後のブロック。
その後、我々は、様々なキャリアとの関係を説明する必要があるだけでなく、全体のデータストリームを分析します
最初は2つのキャリアとキャリアとの間の関係であり、1
私たちは、Hadoopのクライアントの書き込み方法のFSDataOutputStreamを呼び出すときに、必ずしも書き込みデータの真実ではないことを知ってほしいです。
Hadoopの修正パターンを使用して、出力ストリームの設計ので、各パッケージは、別の流れ(追加機能)です。
FSDataOutputStreamは(実際には、パッケージングはDFSOutputStreamあり、DFSOutputStreamはFSOutputSummerを継承)PositionCacheラップFSOutputSummer、PositionCacheを詰め
PositionCache機能は比較的無味なので、主に統計的なデータストリーム、シンプルさ、我々は彼の後に省略します。
全体的な関係を呼び出します。分析するために便利な色の付きました
コールFSDataOutputStream。書き込み(バイト[] B)、すなわち、私たちは通常、書き込まれたデータストリームを、修正関係の様々な地図上の機能(書き込み)に赤の呼び出しの周りに行くことになる、プロセスの途中の機能が省略されています
私たちは、赤、関数の書き込みを見ました。
レッド機能は、実際に私たちの実際の入力データ、セグメントWRITE1プロセスへの入力、およびメソッドWRITE1によって返された値に基づいて、WRITE1の方法は、実際にデータが書き込まれているどのくらい知っています
レッドは本当にただの書き込みデータの機能は、我々はグリーン関数WRITE1を書くことを保証するためにセグメント化することができています
WRITE1では、バッファサイズ、配列バッファ、第1のバッファ層、すなわち、キャリア2が発生したクライアントの各サイズdfs.bytesあたりのチェックサムオプションのチェックサム、一般に、各チェックサムの9倍の大きさでありますセット。
機能はオレンジ関数の関数への呼び出しに含まれるFlushBuffer第二ケースwriteChecksumChunks
この関数は、この関数は、チェックサムを計算するための責任があるので、(チェックサム)writeChecksum /チャンクに分割することと、書き込みチャンクに(紫機能)にwriteChunkを呼び出す必要があります
バッファからのデータは、全データの小さな部分(通常9部)に切断し、各BytesPerCheckSumのサイズ、BytesPerCheckSumの平均値であり、されないforループ緑色のボックス
何ごとに一度チェックサムバイトを計算します。
チャンクとチェックの意味で、後に導入された種
私たちは、オレンジ色の関数writeChecksumChunksを参照してください
レッドボックスはチェックサムを計算するための場所です
チェックサム計算と一般的:データを書き込む場合、データは、(最後のものは、同じサイズでなくてもよい)のサイズのようないくつかの部分に分割され、チェックサム計算の各算出結果
次のデータにエラーが発生したかどうか、データに従ってチェックサム計算を抽出することができる場合、データの先頭または末尾に追加しました。
ここでは、チェックサム計算アルゴリズムのデフォルトCRC32
绿色空心框中的BytesPerChecksum就是每份数据的大小,也就是绿色长方形的大小,每个绿色长方形被叫做Chunk(BytesPerChecksum大小的一份数据)
蓝色空心框部分十分重要,框中方法writeChuck(紫色函数)被DFSOutputStream重写
下面是简单的说明,之后有详解
我们来看看图解,序号表示操作执行顺序
1.第一步其实还有一些检查操作,但主要操作还是创建包
2.第二步是逐块逐块地向Packet里填充校验和
3.第三部是逐块逐块地向Packet填充chunk,chunk是我们实际写入数据被分成等大小的那些块。
4.第四步是记录Packet写入了多少个chunk,当写入的数量超过限制的时候(默认是126,具体会根据bytesPerCheckSum和现在是否写入最后一个数据Packet
进行调整)就会触发M事件(M事件稍后解释)
5.第五步是增加DataStreamer记录的当前块已经写入的数据大小(字节为单位),如果已经写入块的数据等于块的大小,也会触发事件M
事件M:
事件M其实就是调用enqueueCurrentPacketFull函数
这个函数主要分3步,第一步是让当前的Packet入队并且将当前Packet设置为空,第二步是根据边界关系调整下一个Packet的大小,第三步是检查是否块已写满
第一步:
很明显,让Packet入队,并且将当前Packet的引用置空,以便下一次创建一个新的Packet
第二步:
边界调整,什么是边界调整呢?我们要写满一个块,要发送若干个Packet给DataNode,一般Packet的大小是相同的
但是如果Block大小不能被Packet整除的话,就需要调整最后一个Packet的大小,以便正好写满Block。
其实第二步是有两个分支的,上述分析的是第二个分支,第一个分支笔者暂时没有研究透,之后补充。
第三步:
检查是否已经写满一个Block了,如果是,就会把当前包里的数据清空,让这个包作为一个结束通知包,发送给DataNode,告知DataNode
当前的Block已经写完了。
lastPacketInBlock正是来通知DataNode,当前包是Block最后一个包的,没有数据,各项大小都是0,以起到通知作用。
本文分析到此,入队以及之后的操作另外开文分析。
从本文的缓冲以及要写满一个Packet才发送数据我们可以得知 :
有时我们写入了数据,关闭客户端,发现并没有数据被写入HDFS,是因为写入的数据没有写满一个Packet,甚至是没有达到缓冲区大小所以没有被写到HDFS 中。
虽然这一定程度上违背了POSIX标准中对用户操作响应要及时的要求,但适合Hadoop面向大数据传输的特性。
而且如果只传一点数据就写入HDFS,NameNode会因为频繁的请求和大量的文件元数据(metaData)而崩溃宕机
DataNode也会因为频繁琐碎的文件传输请求而导致网络利用率低,甚至宕机。