SlideShare ist ein Scribd-Unternehmen logo
1 von 11
Downloaden Sie, um offline zu lesen
HDFS 写异常分析



文档版本控制
 文档版本号   日期    作者    审核人   说明
 V0.1          刘景龙
目录
1.     目的.................................................................................................................................................. 3

2.     DFSClient 分析 ................................................................................................................................ 3

     2.1      pipeline 建立........................................................................................................................... 6
     2.2      数据传输 ................................................................................................................................. 6
     2.3      close() ...................................................................................................................................... 8

3.     DataNode 分析 ............................................................................................................................... 8

     3.1      错误分析 ................................................................................................................................. 8
     3.2      出错调查 TIPS ......................................................................................................................... 11

4.     常见日志意义 .............................................................................................. 错误!未定义书签。

     4.1      pipeline 建立......................................................................................................................... 11
     4.2      数据传输 ............................................................................................................................... 11
1. 目的
   本文档意在明确写流程过程中操作步骤以及各步中可能出现的异常。各步出现的异常请
见文档中的流程图。
2. DFSClient 分析




      DFSClient       DataStreamer     ResponseProcessor        Namenode      DataNode1            DataNode2                DataNode3

                  write()将packet塞到dataQueue
        0.从data queue中取出packet

                                         1. addBlock()



                                                  2. 建立socket连接



                                              3. 发送WRITE_BLOCK报文



                                                                                            4. new BlockReceiver

                                                                                     5. 建立socket连接

                                                                                  6. 发送WRITE_BLOCK报文

                                                                                                                     7. new BlockReceiver

                                                                                                             8. 建立socket连接

                                                                                                           9. 发送WRITE_BLOCK报文



                                                                                                                                            10. new BlockReceiver

                                                                                                           11. first bad link ack

                                                                                  12. first bad link ack

                                              13. first bad link ack



                            启动ResponseProcessor



                                     将packet从dataQueue中移出,加入到ackQueue

                                              14. 向socket中写packet

                                                                                  15. 向socket中写packet

                                                                                                           16. 向socket中写packet



                                                                                                                                            17. 接收packet,flush到本地磁盘

                                                                                                              18. packet ack



                                                                                                                     19. 接收packet,flush到本地磁盘

                                                                                      20. packet ack



                                                                                            21. 接收packet,flush到本地磁盘

                                                             22. packet ack



                                     23. 收到最后一个packet的ack

                         stop掉ResponseProcessor线程                                                                                           close掉打开的流

                                                                                                                     close掉打开的流

                                     24. close掉使用的流                                         close掉打开的流




           以上为 HDFS 写流程图:
 1.       Rpc 调用 namenode 的 addBlock() 方法来获得新的 block 的 3 个副本位置。
 2.       DFSClient 建立到 primary datanode 的 socket 连接。
 3.       DFSClient 向 primary datanode 发送 WRITE_BLOCK 报文。
4.   Primary datanode 收到 WRITE_BLOCK 报文后,new BlockReceiver 对象,并创建 block
        和 meta 文件。
    5. primary datanode 建立到第二个 datanode 的 socket 连接。
    6. primary datanode 向第二个 datanode 发送 WRITE_BLOCK 报文。
    7. 第二个 datanode 收到 WRITE_BLOCK 报文后,new BlockReceiver 对象。并创建 block
        和 meta 文件。
    8. 第二个 datanode 建立到最后一个 datanode 的 socket 连接。
    9. 第二个 datanode 向最后一个 datanode 发送 WRITE_BLOCK 报文。
    10. 最后一个 datanode 收到 WRITE_BLOCK 报文后,new BlockReceiver 对象并创建 block
        和 meta 文件。
    11. 最后一个 datanode 返回 ack 给第二个 datanode。
    12. 第二个 datanode 返回 ack 给 primary datanode。
    13. primary datanode 返回 ack 给 DFSClient。
    14. DFSClient 向 primary datanode 写 packet。
    15. primary datanode 向第二个 datanode 写 packet
    16. 第二个 datanode 向最后一个 datanode 写 packet。
    17. 最后一个 datanode 写该 packet 数据到 block/meta 文件。
    18. 最后一个 datanode 返给 ack 给第二个 datanode。
    19. 第二个 datanode 写该 packet 数据到 block/meta 文件。
    20. 第二个 datanode 返给 ack 给 primary datanode。
    21. primary datanode 写该 packet 数据到 block/meta 文件。
    22. primary datanode 返给 ack 给 DFSClient。
注:对于非最后 datanode 来讲,发送过程中把数据写到本地磁盘(block/meta)同向上一个
datanode 发送 ack 并无绝对先后关系。datanode 中发送数据和收 ack 是在 BlockReceiver 和
PacketResponser 这 2 个线程中完成。BlockReceiver 负责收到数据,发送给下一个 datanode,
并将数据写本地文件。PacketResponser 负责收到后一个 datanode 的 ack,并将该 ack 转发给
上一个 datanode。当没有数据传输时,pipeline 中各 datanode 通过心跳对连接 keepalive。
BlockReceiver 线程处理数据按照以下顺序:
     1. 收到 packet
     2. 把 packet 写给下一个 datanode
     3. 将 packet flush 到 datanode 本地 block/meta 文件
     4. 将 packet 加入到 ack queue 中
最后一个 datanode 和其他 datanode 中的 PacketResponser 线程以不同方式处理 ack。
     对于最后一个 datanode 处理顺序如下:
         1. 向上一个 datanode 发送 heartbeat (heartbeat 间隔为 dfs.socket.timeout/2, 默
            认为 30s)
         2. 等待 ack queue 中对应 seq number
         3. 如果是最后一个包,finalize block
         4. 向上一个 datanode 发送 ack

   对于其他 datanode 处理顺序如下:
     1. 收到下一个 datanode 的 ack(即使收不到下一个 datanode 的 ack,也会执行第 2
        步)
     2. 等待 ack queue 中对应 seq number
3. 将 ack 发给上一个 datanode
PacketResponser 线程的第二步等 BlockReceiver 线程中的第 4 步完成,才可继续进行下
列步骤。
                                        NotReplicationYet
                                                             重试,dfs.client.block.write.locateFollowBlock.retries,
                                                             默认为5。重试间隔初始为400ms,后一次是前一个的2倍
     Init()            addBlock()                            Rpc调用namenode addblock时,如果该文件的倒数第二个块
                                                             副本小于最小副本数(dfs.replication.min设置,默认为1)
                                                             则报NotReplicationYetException

                 DFSClient建立到primary
                 datanode的socket连接
                                                  重试次数通过dfs.client.block.write.retries设置,默认为3次
                                                                                                   N




                                                                                                                 Pipeline建立
                   DFSClient向primary
              datanode发送WRITE_BLOCK                                                出现此异常的原因为DFSC
                         报文                                                              lient到primary
                                                                                   datanode之间网络出现问题
                         primary
                   datanode返回ack给
  出现异常                 DFSClient



                        Close socket

                                          重试未达到最大重试
                                              次数
                                                             AbandonBlock()
                        Success ?
                                                             重试间隔6s


                 成功

                                                      重试达到最大重试
                                                         次数
                    启动Response
                    Processor线程


                将packet从dataqueue
                 中移出,放到ack                                               Y
                     queue中
                                                                                                到primary
              DFSClient 向primary                                                              datanode的连
              datanode 写packet                                                                 接是否存在
                                                                                                                 数据传输




                    最后一个块?

                                    Y
                                                  出现异常                        processDataError()
                                                             出现异常
                            N
                                         写EOF



                      Socket flush()
                                                                     出现异常                    出现此异常的原因为
                                                                                             DFSClient到primary
               如果是最后块则close流                                                                  datanode之间网络
               ,和ResponseProceessor                         end                                   出现问题
                     线程


写的过程可以分为 3 个阶段 pipeline 建立,数据传输,close()。
2.1 pipeline 建立
   (1) 在pipeline建立的过程中,DFSClient首先rpc调用namenode的addblock(),向namenode
      申请add一个block,并返回该block的三个副本的位置。如果addblock()失败,则进行
      重试,重试次数为dfs.client.block.write.locateFollowBlock.retries, 默认为5。重试间隔
      初始为400ms,后一次是前一次的2倍。如果重试达到最大重试次数,则抛出异常,
      进入(3),如果成功,则顺序执行步骤(2)。
   (2) 如果addBlock()正常返回3个datanode位置信息,则执行以下几步:
       a) 建立到primary datanode的socket连接
       b) 向primary datanode发送WRITE_BLOCK命令
       c) 等待primary datanode的ack应答
       如果以上各步中有一步出错,则进入步骤(3)。如果以上3步都成功,则pipeline
       建立成功。
   (3) 当(1), (2)中出现IOException的时候,会丢弃当前Block,进行重试,重新
      addBlock()。该重试次数通过重试次数通过dfs.client.block.write.retries设置,默认为3
      次
2.2 数据传输
    DFSClient 的数据发送过程比较简单。            就是 DataStreamer 线程从 data queue 中取出 packet,
将其放入 ack queue,然后将该 packet 发给 primary datanode。当数据传输过程中,如果出现
IOException 错误,则会触发出错处理机制。出错处理集中在 processDataError()进行。
    出错处理的过程如下:
    (1) 由于需要数据重发,将 ack queue 中 的 packet 重新塞回到 data queue 中。
    (2) 将之前出错的 datanode 剔除。
    (3) 按照 host:port 的字典序进行排序,将最小的 datanode 作为新的 primary datanode
    (4) 对 primary datanode 进行 block recovery,如果失败,则调用 processDataError()返回,
        由外层循环进行重试。
    (5) 如果成功,则建立到 primary datanode 的 socket 连接。
    (6) 向 primary datanode 发送 WRITE_BLOCK 报文。
    以上各步中出现错误,则 close 掉 socket 之后,函数返回,有外层循环进行重试。
    当一次数据传输出现错误的时候,会调用 processDataError() 尝试进行 block recovery。
举例:我们有 3 个副本分别在 127.0.0.1, 127.0.0.2, 127.0.0.3 3 个 datanode 上。

(1) 初始状态,node 列表

               127.0.0.3   127.0.0.1   127.0.0.2
(2) 127.0.0.1 出错,将 127.0.0.1 踢出,其余 datanode 按照 hostname:port 排序,并以第一
    个 datanode 为 primary(即 127.0.0.2 为 primary)
                                              ,对 127.0.0.2 重试 6 次。

               127.0.0.2   127.0.0.3
(3) 127.0.0.2 出错,将 127.0.0.2 踢出,其余 datanode 按照 hostname:port 排序,并以第一个
    datanode 为 primary(即 127.0.0.3 为 primary)
                                            ,对 127.0.0.3 重试 6 次。
127.0.0.1      127.0.0.3
  (4) 127.0.0.1 出错,将 127.0.0.1 踢出,其余 datanode 按照 hostname:port 排序,并以
  第一个 datanode 为 primary(即 127.0.0.3 为 primary)
                                              ,对 127.0.0.3 重试 6 次。

             127.0.0.3


(5) 127.0.0.3 出错,node list 为空。不再进行 block recovery。
    当一个 block 的其他副本为 3 的时候,进行 block recovery 次数,小于 3 * 6 +1= 19 次,
    则 block recovery 成功。如果等于 19 次,则该 block recovery 失败。
                    processDataError()




                                                close掉流




                                  把ack queue中的packet加入到data
                                            queue中



                                             踢出出错datanode



                                      将剩下的datanode按照host
                                      :port的字典序排序,以最
                                         小的dn作为primary
                                             datanode


                                                对primary
                                              datanode进行       失败    Return
                                              block recovery
                                                   成功


                                        DFSClient建立到primary
                                        datanode的socket连接
                                                                失败


                                          DFSClient向primary
                                     datanode发送WRITE_BLOCK
   出现此异常的原因为DFS                                 报文
      Client到primary
     datanode之间网络                                 primary
         出现问题                                datanode返回ack给
                         throw IOException       DFSClient



                                               Close socket




                                               Success ?

                                                   成功

                                              启动Response
                                              Processor线程
2.3 Close()
                                                                             该异常原因为DFSClient到
                                                                             primary datanode网络连接
                                                                                     出现问题



              将buffer中的数据       flushBuffer()                        Throw IOEXception
               写入到socket中

                                                                                         该函数仅当该DFSClient已经
                                                                                           被close时,才会报出
              不停的等待,直到
               收到全部的ack        flushInternal()

                                                Throw IOEXception
                                                                              异常退出

        关闭DataStreamer和        closeThreads()             Throw IOEXception                    当DataStreamer和
                                                                                           ResponseProcessor线程join
      ResponserProccesor线程                                                                 的时候,如果被interrupt,
                                                                                                 则会报出该异常



                                                                      Throw IOEXception
                              Close连接和打开的流
                                                                                                     Close连接异常
                                                 如果complete不成功


                                                                           Throw IOEXception

                             Namenode.Complete()
                                                                    Complete不成功:complete
                                                                     返回状态为STILL_WAITING
                                                                         成功:返回状态
                                                                        COMPLETE_SUCCESS
                                                                    异常:其他状态,包括安全模
                                                                    式,或者写editlog出现异常


         上图描述了 DFSClient close() 的过程,不难发现,当 flushBuffer(), flushInternal(),
    closeThreads(), close 连接抛出 IOException 时,close 操作直接将 IOException 抛出。而
    Complete()操作一直忙等,直到 complete 成功为止,在 complete 操作中,namenode
    会将之前持有的 lease 释放。
         当 close 异常退出的时候,会有 2 种资源未被 client 处理。
        a) 异常退出时,网络连接未能及时 close (需要修复该 issue)
        b) 异常退出时,lease 未能释放。
            在 namenode 维护 2 个 lease limit。Soft limit 和 hard limit。
                 当 lease 超过 soft limit(1 分钟),另一个 DFSClient append 该文件时会触
             发 lease recovery,且该次 append 失败。但下次重试 append 即可成功。
                 当 lease 超过 hard limit(1 小时) ,则 namenode 触发 lease recovery,释放
             该 lease。
3. DataNode 分析
3.1 错误分析
    Datanode 的行为分为 pipeline 建立和数据传输 2 部分。图 3-1 中描述的是 datanode 在建
立 pipeline 过程中的流程。其中阴影块 receive block() 为数据传输逻辑,在图 3-2 中详细描
述。
收到IOException,重试



收到DFSClient(或上一
个datanode)的connect,                          出错原因:当前datanode到
      建立连接                                   上一个datanode网络出现异
                                                     常




                                               记录日志,
 收到WRITE_BLOCK命令         Throw IOException                                  异常退出
                                               关闭连接


New BlockReceiver对象                 Throw IOException                 出错原因:datanode本地操
(创建block/meta文件)                                                     作会导致IOEXception,有可
                                                                     能是磁盘IO压力造成,需要详
                                                                           细调查

    建立到下一个
                                             Close 掉连接
   datanode的连接
                      Throw IOException


向下一个datanode发送                                          出错原因:当前datanode到下一
                                                          个datanode网络出现异常
 WRITE_BLOCK命令


等待下一个datanode返回                                         Throw IOException
的first bad link的ack
                 成功


                                                                        出错原因:当前datanode到
                    向前一个                                                上一个datanode网络出现异
                                                                                常
                  datanode发送
                      ack


                      Receive
                       block

                                                                参见图3-2



                      success



        图 3-1 datanode 在建立 pipeline 流程
1.启动PacketRespond
                                er线程
                                                                                   该函数出现IOException的原
                                                                                    因是上一个datanode到本
                                                                                    datanode的网络连接异常
                            2.readNextPacke
                                   t
                                                                                      如果是此种异常,则需要进一
                                                                                           步定位

                           3.setBlockPosition

                                                                                            该函数出现IOException的原
                                                                                             因是本datanode到下一个
                                                                                             datanode的网络连接异常
                            4.将读入的packet数
                             据写入mirror out

                        5.如果该datanode为pipeline中
                           最后一个verifyChunks
            还有后续包

                                                                             Ioexception
                              Finalized ?

                                   N

                    Y       6.将数据写到磁盘。                        7.CheckData
                            包括写block和meta                      nodeError
                                                IOException

                                                                                           该函数出现IOException的原
                                                                                           因是本datanode的磁盘异常
                              8.将整个packet
                          flush。包括block和meta




                        9.将pkt放入response队列中,由
                         PacketResponder线程发出应答



                          10.向mirror out写EOF        Throw IOException   12.cleanupBlock


                                                                        该函数出现IOException的原
                        11.关闭PacketResponder线程                           因是本datanode到下一个
                                                                         datanode的网络连接异常




                             图 3-2 datanode 在数据传输流程
      不难发现,在建立 pipeline 的过程中有 3 种异常。
1) Datanode 作为 socket server 时, accept 到 DFSClient 来的请求时,
                                在                           如果出现异常,
则忽略异常,datanode 继续 accept 连接。
2) 当 datanode 向下一个 datanode 建立连接,          发送 WRITE_BLOCK 指令或者在接受 first
bad link ack 时出现错误时,   datanode 会 close 掉同下一个 datanode 的网络连接并向上一
个 datanode(或者是 DFSClient)发送 ack 并 receive block 接受数据。
3) 其他情况出现 IOException 都会导致该该 DataXeceiver 线程异常退出。导致这种异
常的原因有二:
      a) 同上一个 datanode 交互。包括接收 WRITE_BLOCK 命令和向上一个 datanode
           发送 ack。此时,可能是由于上一个 datanode 到该 datanode 的网络连接繁忙。
           可检查事发时刻网络状况。
b)    Create 本地 block 和 meta 文件。
                                       出现此类错误时,     有可能是由于创建本地 block
              和 meta 文件时出错,具体情况可检查 datanode 日志。
    以上问题的定位,可通过日志中打出的 stack 信息协助定位。
         Datanode 中数据传输在 receive block 中完成。各步网络及磁盘操作中皆可能出现
    IOException。在 receive block 中,并无重试机制。出现错误会导致 DataXeceiver 线程异
    常退出。数据传输过程中的网络和磁盘繁忙皆会导致此类错误。
3.2 出错调查 tips
         当出现写异常时,可以通过查看写错误时对应的 meta 及 block 文件。
         如果文件已经存在,且不为空,则意味着 pipeline 已经建立。错误出现在数据传输
     过程中。可对照图 3-2 协助问题定位。
         如果 meta/block 文件不存在,       有可能是由于 datanode 重启,或者 new BlockReceiver
     对象,未能成功,需要进一步定位。
         如果 meta/block 文件为空,则可证明 new BlockReceiver 对象成功,可检查下一个
     datanode 协助定位问题。

4. 常见日志意义
4.1 pipeline 建立
case1 :DFSClient 中报 warn 日志 NotReplicatedYetException sleeping <路径> retries left,

无该日志                                      addBlock ()一次成功
小于 4 次                                    addBlock()通过重试成功
等于 4 次后紧跟 warn 日志 ”DataStreamer           addBlock() 失败
Exception:”
等于 4 次后紧跟 warn 日志 ”DataStreamer           addBlock() 在最后一次重试成功
Exception:”
处理方式:如果 addBlock()失败,则需要查看当时 namenode 的日志。
Case 2: 出现 info 日志 “Excluding node:”, 后紧接着 “Abandoning block” 代表建立 pipeline
时出错,进行 abandon block,然后重试。
处理方式:如果重试次数小于 5,则可忽略。
Case 3:出现 info 日志“Exception in createBlockOutputStream” 后有“Bad connect ack with
firstBadLink” 代表建立 pipeline 的时候,  接收日志中指定的 datanode 的 ack 时,    socket timeout。
处理方式:检查日志中指定 datanode 的负载状况,有可能是网络繁忙造成。

4.2 数据传输
Case 4:出现warn日志"Error Recovery for block " + block + " failed " +
                    " because recovery from primary datanode " +
                    primaryNode + " failed " + recoveryErrorCount +
                    " times. " + " Pipeline was "
    代表日志中指定的 datanode 出现 block recovery 失败
处理方式:查看指定 datanode 的日志和监控有可能是由于当时网络繁忙或者 datanode 其他
原因造成出错。当文件副本数位 3 时,Error Recovery for block 出现 19 次,则表示该 block
recovery 失败。应查看对应 datanode 的日志,以进一步定位问题。
Case 5: 出现 info 日志“Exception in receiveBlock for block”日志时,说明是数据传输过程
中出现异常。需要根据该日志中报出的 block id 和异常栈协助定位。

Weitere ähnliche Inhalte

Andere mochten auch

Metrics, Pitfalls and Useful Metrics
Metrics, Pitfalls and Useful MetricsMetrics, Pitfalls and Useful Metrics
Metrics, Pitfalls and Useful MetricsAjay Balamurugadas
 
CETS 2012, Susan Fisher, handout for Mobile Decisions: Ensuring the Solution ...
CETS 2012, Susan Fisher, handout for Mobile Decisions: Ensuring the Solution ...CETS 2012, Susan Fisher, handout for Mobile Decisions: Ensuring the Solution ...
CETS 2012, Susan Fisher, handout for Mobile Decisions: Ensuring the Solution ...Chicago eLearning & Technology Showcase
 
투이컨설팅 제40회 Y세미나 : 설문결과
투이컨설팅 제40회 Y세미나 : 설문결과투이컨설팅 제40회 Y세미나 : 설문결과
투이컨설팅 제40회 Y세미나 : 설문결과2econsulting
 
Role of Social Media in Education
Role of Social Media in EducationRole of Social Media in Education
Role of Social Media in EducationDr. Muhammad Iqbal
 
5Q Communications - Top 10 Tips for Effective Web Ministry
5Q Communications - Top 10 Tips for Effective Web Ministry5Q Communications - Top 10 Tips for Effective Web Ministry
5Q Communications - Top 10 Tips for Effective Web MinistryFive Q
 
Moneda
MonedaMoneda
MonedaEver
 
Callture turnkey platform presentation
Callture turnkey platform presentationCallture turnkey platform presentation
Callture turnkey platform presentationCallture Inc
 
Agri presentation 7th_sept2009
Agri presentation 7th_sept2009Agri presentation 7th_sept2009
Agri presentation 7th_sept2009Prafulla Tekriwal
 
Linkedin Steps To Success
Linkedin Steps To SuccessLinkedin Steps To Success
Linkedin Steps To SuccessKatiebackagain
 
Development of the Logistics Sector in the United States: Past, Present and F...
Development of the Logistics Sector in the United States: Past, Present and F...Development of the Logistics Sector in the United States: Past, Present and F...
Development of the Logistics Sector in the United States: Past, Present and F...Technopreneurs Association of Malaysia
 
Hdfs原理及实现
Hdfs原理及实现Hdfs原理及实现
Hdfs原理及实现baggioss
 

Andere mochten auch (20)

CamTech 2
CamTech 2CamTech 2
CamTech 2
 
Metrics, Pitfalls and Useful Metrics
Metrics, Pitfalls and Useful MetricsMetrics, Pitfalls and Useful Metrics
Metrics, Pitfalls and Useful Metrics
 
Nzas 2014
Nzas 2014Nzas 2014
Nzas 2014
 
Proyecto Incredibox
Proyecto IncrediboxProyecto Incredibox
Proyecto Incredibox
 
CETS 2012, Susan Fisher, handout for Mobile Decisions: Ensuring the Solution ...
CETS 2012, Susan Fisher, handout for Mobile Decisions: Ensuring the Solution ...CETS 2012, Susan Fisher, handout for Mobile Decisions: Ensuring the Solution ...
CETS 2012, Susan Fisher, handout for Mobile Decisions: Ensuring the Solution ...
 
투이컨설팅 제40회 Y세미나 : 설문결과
투이컨설팅 제40회 Y세미나 : 설문결과투이컨설팅 제40회 Y세미나 : 설문결과
투이컨설팅 제40회 Y세미나 : 설문결과
 
BUSINESS LOAN CONTRACT MOU
BUSINESS LOAN CONTRACT MOUBUSINESS LOAN CONTRACT MOU
BUSINESS LOAN CONTRACT MOU
 
Role of Social Media in Education
Role of Social Media in EducationRole of Social Media in Education
Role of Social Media in Education
 
5Q Communications - Top 10 Tips for Effective Web Ministry
5Q Communications - Top 10 Tips for Effective Web Ministry5Q Communications - Top 10 Tips for Effective Web Ministry
5Q Communications - Top 10 Tips for Effective Web Ministry
 
Moneda
MonedaMoneda
Moneda
 
Unit 7 lesson d
Unit 7  lesson dUnit 7  lesson d
Unit 7 lesson d
 
Callture turnkey platform presentation
Callture turnkey platform presentationCallture turnkey platform presentation
Callture turnkey platform presentation
 
Case Study - France ICT Adoption Program for Small Businesses
Case Study - France ICT Adoption Program for Small BusinessesCase Study - France ICT Adoption Program for Small Businesses
Case Study - France ICT Adoption Program for Small Businesses
 
Agri presentation 7th_sept2009
Agri presentation 7th_sept2009Agri presentation 7th_sept2009
Agri presentation 7th_sept2009
 
Cets 2015 buteyn animation in e learning
Cets 2015 buteyn animation in e learningCets 2015 buteyn animation in e learning
Cets 2015 buteyn animation in e learning
 
Linkedin Steps To Success
Linkedin Steps To SuccessLinkedin Steps To Success
Linkedin Steps To Success
 
Development of the Logistics Sector in the United States: Past, Present and F...
Development of the Logistics Sector in the United States: Past, Present and F...Development of the Logistics Sector in the United States: Past, Present and F...
Development of the Logistics Sector in the United States: Past, Present and F...
 
Demystifying and Monetizing the Cloud
Demystifying and Monetizing the CloudDemystifying and Monetizing the Cloud
Demystifying and Monetizing the Cloud
 
Insider’s Briefing: Entertainment and Media Sector in Los Angeles
Insider’s Briefing: Entertainment and Media Sector in Los AngelesInsider’s Briefing: Entertainment and Media Sector in Los Angeles
Insider’s Briefing: Entertainment and Media Sector in Los Angeles
 
Hdfs原理及实现
Hdfs原理及实现Hdfs原理及实现
Hdfs原理及实现
 

Mehr von baggioss

Hbase性能测试文档
Hbase性能测试文档Hbase性能测试文档
Hbase性能测试文档baggioss
 
Hbase使用hadoop分析
Hbase使用hadoop分析Hbase使用hadoop分析
Hbase使用hadoop分析baggioss
 
Hadoop基线选定
Hadoop基线选定Hadoop基线选定
Hadoop基线选定baggioss
 
Hic 2011 realtime_analytics_at_facebook
Hic 2011 realtime_analytics_at_facebookHic 2011 realtime_analytics_at_facebook
Hic 2011 realtime_analytics_at_facebookbaggioss
 
[Hi c2011]building mission critical messaging system(guoqiang jerry)
[Hi c2011]building mission critical messaging system(guoqiang jerry)[Hi c2011]building mission critical messaging system(guoqiang jerry)
[Hi c2011]building mission critical messaging system(guoqiang jerry)baggioss
 
Hdfs introduction
Hdfs introductionHdfs introduction
Hdfs introductionbaggioss
 

Mehr von baggioss (10)

Hbase性能测试文档
Hbase性能测试文档Hbase性能测试文档
Hbase性能测试文档
 
Hbase使用hadoop分析
Hbase使用hadoop分析Hbase使用hadoop分析
Hbase使用hadoop分析
 
Hadoop基线选定
Hadoop基线选定Hadoop基线选定
Hadoop基线选定
 
Hic 2011 realtime_analytics_at_facebook
Hic 2011 realtime_analytics_at_facebookHic 2011 realtime_analytics_at_facebook
Hic 2011 realtime_analytics_at_facebook
 
[Hi c2011]building mission critical messaging system(guoqiang jerry)
[Hi c2011]building mission critical messaging system(guoqiang jerry)[Hi c2011]building mission critical messaging system(guoqiang jerry)
[Hi c2011]building mission critical messaging system(guoqiang jerry)
 
Hic2011
Hic2011Hic2011
Hic2011
 
Hdfs introduction
Hdfs introductionHdfs introduction
Hdfs introduction
 
Hbase
HbaseHbase
Hbase
 
Hdfs
HdfsHdfs
Hdfs
 
Hdfs
HdfsHdfs
Hdfs
 

Hdfs写流程异常处理

  • 1. HDFS 写异常分析 文档版本控制 文档版本号 日期 作者 审核人 说明 V0.1 刘景龙
  • 2. 目录 1. 目的.................................................................................................................................................. 3 2. DFSClient 分析 ................................................................................................................................ 3 2.1 pipeline 建立........................................................................................................................... 6 2.2 数据传输 ................................................................................................................................. 6 2.3 close() ...................................................................................................................................... 8 3. DataNode 分析 ............................................................................................................................... 8 3.1 错误分析 ................................................................................................................................. 8 3.2 出错调查 TIPS ......................................................................................................................... 11 4. 常见日志意义 .............................................................................................. 错误!未定义书签。 4.1 pipeline 建立......................................................................................................................... 11 4.2 数据传输 ............................................................................................................................... 11
  • 3. 1. 目的 本文档意在明确写流程过程中操作步骤以及各步中可能出现的异常。各步出现的异常请 见文档中的流程图。 2. DFSClient 分析 DFSClient DataStreamer ResponseProcessor Namenode DataNode1 DataNode2 DataNode3 write()将packet塞到dataQueue 0.从data queue中取出packet 1. addBlock() 2. 建立socket连接 3. 发送WRITE_BLOCK报文 4. new BlockReceiver 5. 建立socket连接 6. 发送WRITE_BLOCK报文 7. new BlockReceiver 8. 建立socket连接 9. 发送WRITE_BLOCK报文 10. new BlockReceiver 11. first bad link ack 12. first bad link ack 13. first bad link ack 启动ResponseProcessor 将packet从dataQueue中移出,加入到ackQueue 14. 向socket中写packet 15. 向socket中写packet 16. 向socket中写packet 17. 接收packet,flush到本地磁盘 18. packet ack 19. 接收packet,flush到本地磁盘 20. packet ack 21. 接收packet,flush到本地磁盘 22. packet ack 23. 收到最后一个packet的ack stop掉ResponseProcessor线程 close掉打开的流 close掉打开的流 24. close掉使用的流 close掉打开的流 以上为 HDFS 写流程图: 1. Rpc 调用 namenode 的 addBlock() 方法来获得新的 block 的 3 个副本位置。 2. DFSClient 建立到 primary datanode 的 socket 连接。 3. DFSClient 向 primary datanode 发送 WRITE_BLOCK 报文。
  • 4. 4. Primary datanode 收到 WRITE_BLOCK 报文后,new BlockReceiver 对象,并创建 block 和 meta 文件。 5. primary datanode 建立到第二个 datanode 的 socket 连接。 6. primary datanode 向第二个 datanode 发送 WRITE_BLOCK 报文。 7. 第二个 datanode 收到 WRITE_BLOCK 报文后,new BlockReceiver 对象。并创建 block 和 meta 文件。 8. 第二个 datanode 建立到最后一个 datanode 的 socket 连接。 9. 第二个 datanode 向最后一个 datanode 发送 WRITE_BLOCK 报文。 10. 最后一个 datanode 收到 WRITE_BLOCK 报文后,new BlockReceiver 对象并创建 block 和 meta 文件。 11. 最后一个 datanode 返回 ack 给第二个 datanode。 12. 第二个 datanode 返回 ack 给 primary datanode。 13. primary datanode 返回 ack 给 DFSClient。 14. DFSClient 向 primary datanode 写 packet。 15. primary datanode 向第二个 datanode 写 packet 16. 第二个 datanode 向最后一个 datanode 写 packet。 17. 最后一个 datanode 写该 packet 数据到 block/meta 文件。 18. 最后一个 datanode 返给 ack 给第二个 datanode。 19. 第二个 datanode 写该 packet 数据到 block/meta 文件。 20. 第二个 datanode 返给 ack 给 primary datanode。 21. primary datanode 写该 packet 数据到 block/meta 文件。 22. primary datanode 返给 ack 给 DFSClient。 注:对于非最后 datanode 来讲,发送过程中把数据写到本地磁盘(block/meta)同向上一个 datanode 发送 ack 并无绝对先后关系。datanode 中发送数据和收 ack 是在 BlockReceiver 和 PacketResponser 这 2 个线程中完成。BlockReceiver 负责收到数据,发送给下一个 datanode, 并将数据写本地文件。PacketResponser 负责收到后一个 datanode 的 ack,并将该 ack 转发给 上一个 datanode。当没有数据传输时,pipeline 中各 datanode 通过心跳对连接 keepalive。 BlockReceiver 线程处理数据按照以下顺序: 1. 收到 packet 2. 把 packet 写给下一个 datanode 3. 将 packet flush 到 datanode 本地 block/meta 文件 4. 将 packet 加入到 ack queue 中 最后一个 datanode 和其他 datanode 中的 PacketResponser 线程以不同方式处理 ack。 对于最后一个 datanode 处理顺序如下: 1. 向上一个 datanode 发送 heartbeat (heartbeat 间隔为 dfs.socket.timeout/2, 默 认为 30s) 2. 等待 ack queue 中对应 seq number 3. 如果是最后一个包,finalize block 4. 向上一个 datanode 发送 ack 对于其他 datanode 处理顺序如下: 1. 收到下一个 datanode 的 ack(即使收不到下一个 datanode 的 ack,也会执行第 2 步) 2. 等待 ack queue 中对应 seq number
  • 5. 3. 将 ack 发给上一个 datanode PacketResponser 线程的第二步等 BlockReceiver 线程中的第 4 步完成,才可继续进行下 列步骤。 NotReplicationYet 重试,dfs.client.block.write.locateFollowBlock.retries, 默认为5。重试间隔初始为400ms,后一次是前一个的2倍 Init() addBlock() Rpc调用namenode addblock时,如果该文件的倒数第二个块 副本小于最小副本数(dfs.replication.min设置,默认为1) 则报NotReplicationYetException DFSClient建立到primary datanode的socket连接 重试次数通过dfs.client.block.write.retries设置,默认为3次 N Pipeline建立 DFSClient向primary datanode发送WRITE_BLOCK 出现此异常的原因为DFSC 报文 lient到primary datanode之间网络出现问题 primary datanode返回ack给 出现异常 DFSClient Close socket 重试未达到最大重试 次数 AbandonBlock() Success ? 重试间隔6s 成功 重试达到最大重试 次数 启动Response Processor线程 将packet从dataqueue 中移出,放到ack Y queue中 到primary DFSClient 向primary datanode的连 datanode 写packet 接是否存在 数据传输 最后一个块? Y 出现异常 processDataError() 出现异常 N 写EOF Socket flush() 出现异常 出现此异常的原因为 DFSClient到primary 如果是最后块则close流 datanode之间网络 ,和ResponseProceessor end 出现问题 线程 写的过程可以分为 3 个阶段 pipeline 建立,数据传输,close()。
  • 6. 2.1 pipeline 建立 (1) 在pipeline建立的过程中,DFSClient首先rpc调用namenode的addblock(),向namenode 申请add一个block,并返回该block的三个副本的位置。如果addblock()失败,则进行 重试,重试次数为dfs.client.block.write.locateFollowBlock.retries, 默认为5。重试间隔 初始为400ms,后一次是前一次的2倍。如果重试达到最大重试次数,则抛出异常, 进入(3),如果成功,则顺序执行步骤(2)。 (2) 如果addBlock()正常返回3个datanode位置信息,则执行以下几步: a) 建立到primary datanode的socket连接 b) 向primary datanode发送WRITE_BLOCK命令 c) 等待primary datanode的ack应答 如果以上各步中有一步出错,则进入步骤(3)。如果以上3步都成功,则pipeline 建立成功。 (3) 当(1), (2)中出现IOException的时候,会丢弃当前Block,进行重试,重新 addBlock()。该重试次数通过重试次数通过dfs.client.block.write.retries设置,默认为3 次 2.2 数据传输 DFSClient 的数据发送过程比较简单。 就是 DataStreamer 线程从 data queue 中取出 packet, 将其放入 ack queue,然后将该 packet 发给 primary datanode。当数据传输过程中,如果出现 IOException 错误,则会触发出错处理机制。出错处理集中在 processDataError()进行。 出错处理的过程如下: (1) 由于需要数据重发,将 ack queue 中 的 packet 重新塞回到 data queue 中。 (2) 将之前出错的 datanode 剔除。 (3) 按照 host:port 的字典序进行排序,将最小的 datanode 作为新的 primary datanode (4) 对 primary datanode 进行 block recovery,如果失败,则调用 processDataError()返回, 由外层循环进行重试。 (5) 如果成功,则建立到 primary datanode 的 socket 连接。 (6) 向 primary datanode 发送 WRITE_BLOCK 报文。 以上各步中出现错误,则 close 掉 socket 之后,函数返回,有外层循环进行重试。 当一次数据传输出现错误的时候,会调用 processDataError() 尝试进行 block recovery。 举例:我们有 3 个副本分别在 127.0.0.1, 127.0.0.2, 127.0.0.3 3 个 datanode 上。 (1) 初始状态,node 列表 127.0.0.3 127.0.0.1 127.0.0.2 (2) 127.0.0.1 出错,将 127.0.0.1 踢出,其余 datanode 按照 hostname:port 排序,并以第一 个 datanode 为 primary(即 127.0.0.2 为 primary) ,对 127.0.0.2 重试 6 次。 127.0.0.2 127.0.0.3 (3) 127.0.0.2 出错,将 127.0.0.2 踢出,其余 datanode 按照 hostname:port 排序,并以第一个 datanode 为 primary(即 127.0.0.3 为 primary) ,对 127.0.0.3 重试 6 次。
  • 7. 127.0.0.1 127.0.0.3 (4) 127.0.0.1 出错,将 127.0.0.1 踢出,其余 datanode 按照 hostname:port 排序,并以 第一个 datanode 为 primary(即 127.0.0.3 为 primary) ,对 127.0.0.3 重试 6 次。 127.0.0.3 (5) 127.0.0.3 出错,node list 为空。不再进行 block recovery。 当一个 block 的其他副本为 3 的时候,进行 block recovery 次数,小于 3 * 6 +1= 19 次, 则 block recovery 成功。如果等于 19 次,则该 block recovery 失败。 processDataError() close掉流 把ack queue中的packet加入到data queue中 踢出出错datanode 将剩下的datanode按照host :port的字典序排序,以最 小的dn作为primary datanode 对primary datanode进行 失败 Return block recovery 成功 DFSClient建立到primary datanode的socket连接 失败 DFSClient向primary datanode发送WRITE_BLOCK 出现此异常的原因为DFS 报文 Client到primary datanode之间网络 primary 出现问题 datanode返回ack给 throw IOException DFSClient Close socket Success ? 成功 启动Response Processor线程
  • 8. 2.3 Close() 该异常原因为DFSClient到 primary datanode网络连接 出现问题 将buffer中的数据 flushBuffer() Throw IOEXception 写入到socket中 该函数仅当该DFSClient已经 被close时,才会报出 不停的等待,直到 收到全部的ack flushInternal() Throw IOEXception 异常退出 关闭DataStreamer和 closeThreads() Throw IOEXception 当DataStreamer和 ResponseProcessor线程join ResponserProccesor线程 的时候,如果被interrupt, 则会报出该异常 Throw IOEXception Close连接和打开的流 Close连接异常 如果complete不成功 Throw IOEXception Namenode.Complete() Complete不成功:complete 返回状态为STILL_WAITING 成功:返回状态 COMPLETE_SUCCESS 异常:其他状态,包括安全模 式,或者写editlog出现异常 上图描述了 DFSClient close() 的过程,不难发现,当 flushBuffer(), flushInternal(), closeThreads(), close 连接抛出 IOException 时,close 操作直接将 IOException 抛出。而 Complete()操作一直忙等,直到 complete 成功为止,在 complete 操作中,namenode 会将之前持有的 lease 释放。 当 close 异常退出的时候,会有 2 种资源未被 client 处理。 a) 异常退出时,网络连接未能及时 close (需要修复该 issue) b) 异常退出时,lease 未能释放。 在 namenode 维护 2 个 lease limit。Soft limit 和 hard limit。 当 lease 超过 soft limit(1 分钟),另一个 DFSClient append 该文件时会触 发 lease recovery,且该次 append 失败。但下次重试 append 即可成功。 当 lease 超过 hard limit(1 小时) ,则 namenode 触发 lease recovery,释放 该 lease。 3. DataNode 分析 3.1 错误分析 Datanode 的行为分为 pipeline 建立和数据传输 2 部分。图 3-1 中描述的是 datanode 在建 立 pipeline 过程中的流程。其中阴影块 receive block() 为数据传输逻辑,在图 3-2 中详细描 述。
  • 9. 收到IOException,重试 收到DFSClient(或上一 个datanode)的connect, 出错原因:当前datanode到 建立连接 上一个datanode网络出现异 常 记录日志, 收到WRITE_BLOCK命令 Throw IOException 异常退出 关闭连接 New BlockReceiver对象 Throw IOException 出错原因:datanode本地操 (创建block/meta文件) 作会导致IOEXception,有可 能是磁盘IO压力造成,需要详 细调查 建立到下一个 Close 掉连接 datanode的连接 Throw IOException 向下一个datanode发送 出错原因:当前datanode到下一 个datanode网络出现异常 WRITE_BLOCK命令 等待下一个datanode返回 Throw IOException 的first bad link的ack 成功 出错原因:当前datanode到 向前一个 上一个datanode网络出现异 常 datanode发送 ack Receive block 参见图3-2 success 图 3-1 datanode 在建立 pipeline 流程
  • 10. 1.启动PacketRespond er线程 该函数出现IOException的原 因是上一个datanode到本 datanode的网络连接异常 2.readNextPacke t 如果是此种异常,则需要进一 步定位 3.setBlockPosition 该函数出现IOException的原 因是本datanode到下一个 datanode的网络连接异常 4.将读入的packet数 据写入mirror out 5.如果该datanode为pipeline中 最后一个verifyChunks 还有后续包 Ioexception Finalized ? N Y 6.将数据写到磁盘。 7.CheckData 包括写block和meta nodeError IOException 该函数出现IOException的原 因是本datanode的磁盘异常 8.将整个packet flush。包括block和meta 9.将pkt放入response队列中,由 PacketResponder线程发出应答 10.向mirror out写EOF Throw IOException 12.cleanupBlock 该函数出现IOException的原 11.关闭PacketResponder线程 因是本datanode到下一个 datanode的网络连接异常 图 3-2 datanode 在数据传输流程 不难发现,在建立 pipeline 的过程中有 3 种异常。 1) Datanode 作为 socket server 时, accept 到 DFSClient 来的请求时, 在 如果出现异常, 则忽略异常,datanode 继续 accept 连接。 2) 当 datanode 向下一个 datanode 建立连接, 发送 WRITE_BLOCK 指令或者在接受 first bad link ack 时出现错误时, datanode 会 close 掉同下一个 datanode 的网络连接并向上一 个 datanode(或者是 DFSClient)发送 ack 并 receive block 接受数据。 3) 其他情况出现 IOException 都会导致该该 DataXeceiver 线程异常退出。导致这种异 常的原因有二: a) 同上一个 datanode 交互。包括接收 WRITE_BLOCK 命令和向上一个 datanode 发送 ack。此时,可能是由于上一个 datanode 到该 datanode 的网络连接繁忙。 可检查事发时刻网络状况。
  • 11. b) Create 本地 block 和 meta 文件。 出现此类错误时, 有可能是由于创建本地 block 和 meta 文件时出错,具体情况可检查 datanode 日志。 以上问题的定位,可通过日志中打出的 stack 信息协助定位。 Datanode 中数据传输在 receive block 中完成。各步网络及磁盘操作中皆可能出现 IOException。在 receive block 中,并无重试机制。出现错误会导致 DataXeceiver 线程异 常退出。数据传输过程中的网络和磁盘繁忙皆会导致此类错误。 3.2 出错调查 tips 当出现写异常时,可以通过查看写错误时对应的 meta 及 block 文件。 如果文件已经存在,且不为空,则意味着 pipeline 已经建立。错误出现在数据传输 过程中。可对照图 3-2 协助问题定位。 如果 meta/block 文件不存在, 有可能是由于 datanode 重启,或者 new BlockReceiver 对象,未能成功,需要进一步定位。 如果 meta/block 文件为空,则可证明 new BlockReceiver 对象成功,可检查下一个 datanode 协助定位问题。 4. 常见日志意义 4.1 pipeline 建立 case1 :DFSClient 中报 warn 日志 NotReplicatedYetException sleeping <路径> retries left, 无该日志 addBlock ()一次成功 小于 4 次 addBlock()通过重试成功 等于 4 次后紧跟 warn 日志 ”DataStreamer addBlock() 失败 Exception:” 等于 4 次后紧跟 warn 日志 ”DataStreamer addBlock() 在最后一次重试成功 Exception:” 处理方式:如果 addBlock()失败,则需要查看当时 namenode 的日志。 Case 2: 出现 info 日志 “Excluding node:”, 后紧接着 “Abandoning block” 代表建立 pipeline 时出错,进行 abandon block,然后重试。 处理方式:如果重试次数小于 5,则可忽略。 Case 3:出现 info 日志“Exception in createBlockOutputStream” 后有“Bad connect ack with firstBadLink” 代表建立 pipeline 的时候, 接收日志中指定的 datanode 的 ack 时, socket timeout。 处理方式:检查日志中指定 datanode 的负载状况,有可能是网络繁忙造成。 4.2 数据传输 Case 4:出现warn日志"Error Recovery for block " + block + " failed " + " because recovery from primary datanode " + primaryNode + " failed " + recoveryErrorCount + " times. " + " Pipeline was " 代表日志中指定的 datanode 出现 block recovery 失败 处理方式:查看指定 datanode 的日志和监控有可能是由于当时网络繁忙或者 datanode 其他 原因造成出错。当文件副本数位 3 时,Error Recovery for block 出现 19 次,则表示该 block recovery 失败。应查看对应 datanode 的日志,以进一步定位问题。 Case 5: 出现 info 日志“Exception in receiveBlock for block”日志时,说明是数据传输过程 中出现异常。需要根据该日志中报出的 block id 和异常栈协助定位。