HDFS的讀寫流程

laoma8888發表於2018-08-07

hdfs寫資料流程
 通過以下程式碼進入寫資料流程:

		FSDataOutputStream fsous=fileSystem.create(new Path("/user.txt"));
		fsous.write("fdsafdsafdsafs".getBytes());

在這裡插入圖片描述
 由create方法進入客戶端程式碼,通過DistributedFileSystem獲取到DFSClient物件最終在DFSOutputStream類中通過NameNodeRpcServer的代理物件遠端呼叫NameNodeRpcServer的create方法建立檔案,同時這裡還會啟動一個非常重要的執行緒DataStreamer。NameNode通過FSNamesystem建立檔案後修改記憶體中後設資料資訊並將操作日誌寫入磁碟,具體流程可見NameNode後設資料管理。同時在建立檔案後會為這個檔案建立一個檔案契約(lease)並返回給客戶端,用於控制多個客戶端寫同一個檔案,建立契約後NameNode會啟動一個後臺執行緒用於監控契約狀態,當契約超過1小時沒有續約後會在儲存契約的sortMap中將之移除,這裡用sortMap來儲存契約主要是可以排序,樹型結構,最早續約的排在最上面的節點,這樣這個後臺執行緒只需判斷這個最早續約的契約是否超過一小時沒有續約就行。客戶端拿到契約後也會啟動一個後臺執行緒用於續約,並且每隔1秒檢查一次契約狀態,當超過30秒沒有續約後會主動通過rpc向NameNodeRpcServer發起續約請求,NameNode獲得請求後會將sortMap中對應的契約的上次續約時間進行更新。至此create的流程基本走完。
 write寫入資料,在客戶單最終會呼叫到FSOutputSummer的write方法,這裡開始將資料寫成一個個的Chunk,一個chunk512個位元組+4個位元組的校驗資訊,一個packet預設64K由127個chunk組成。當一個packet寫滿或者一個block塊(預設128M)寫滿時,會將packet放入dataQueue佇列,同時之前啟動的DataStreamer執行緒因為dataQueue沒有資料一直在等待,此刻會被喚醒,具體後續程式碼流程在該執行緒中。
DataStreamer的工作
 1、DataStreamer此時會通過rpc想NameNode請求block塊,NameNode會根據請求及配置的副本數和負載均衡策略為合理的機器建立對應的block資訊,並將這些block塊資訊新增到之前建立的INodeFile上,同時返回給DataStreamer。
 2、這時DataStreamer會根據block資訊建立資料管道,會向第一個DataNode傳送socket請求建立連線,通過DataNode啟動時啟動的執行緒DataXceiverServer來連線(具體流程見DataNode的啟動流程和心跳),後續的連線由相應的DataNode依次通過socket以同樣的方式建立連線形成管道,並且在傳送socket連線時會有三次重試機會,都失敗則會放棄這個DataNode重新申請block,申請新的block時會將連線不上的block資訊返回給NameNode避免再次被分配到連線不上的那臺DataNode。
 3、啟動ResponseProcessor執行緒,用於接收下游DataNode返回的ack資訊,若結果是寫入成功,則將ackQueue佇列中對應的packet移除,然後傳送喚醒DataStreamer下一個packet,若結果是寫入失敗,則會將ackQueu中對應的packet重新寫入dataQueue中,繼續傳送實現容錯。
 4、傳送資料前會將dataQueue對應的packet移除,新增到ackQueue中,一方面是為了第3點的容錯,一方面是給dataQueue騰出空間。
 5、正式傳送資料,通過流對拷的形式將資料一個packet一個packet傳送給下游的DataNode。

 資料到達第一個DataNode這裡時,通過DataXceiverServer執行緒開啟DataXceiver執行緒,一個DataXceiver執行緒對應一個block塊,根據請求型別來執行後續程式碼,這裡我們是寫對應的是WRITE_BLOCK,然後會建立一個關鍵的執行緒BlockReceiver,BlockReceiver執行緒主要有三個作用:

  1. 通過socket連線下游DataNode。
  2. 啟動PacketResponder執行緒用於監聽下游返回的ack結果資訊,作用類似於客戶端中啟動的ResponseProcessor執行緒。結果成功則移除ackQueue中的packet,失敗則將ackQueue中的packet繼續傳送下游。
  3. 接收上游傳送過來的packet資料,接收到資料時首先將packet寫入ackQueue佇列中,然後將這個packet傳送給下游節點,最後根據之前客戶端將資料寫成chunk時的校驗資訊進行資料的校驗,校驗通過將資料寫入到磁碟。
     資料再管道流通時,若寫入失敗有ackQueue進行容錯,若DataNode當機或者因為其他原因socket連線不上,在三次重試完後會將失效的DataNode移除管道列表繼續傳送資料,寫資料不要保證所有副本都寫入成功,只需要管道中的DataNode寫入成功就像,最低一個,後續NameNode會自動平衡副本數。

相關文章