Hadoop实践之HDFS

What?


Hadoop 生态

来自于 Google 03 年发布 3 大论文, GFS、mapreduce、Bigtable ;Dougcutting 用 Java 实现)

HDFS:

Hadoop Distributed File System 分布式存储系统

http://hadoop.apache.org

high-throughput 高吞吐

  • Hadoop Common
  • Hadoop Distributed File System (HDFS™)
  • Hadoop YARN
  • Hadoop MapReduce

组件

  • name node 主节点
    • 接收客户端读写服务
    • 接收datanode 汇报的block位置信息
    • 保存metadate元信息(基于内存存储,不会和磁盘发生交换)
      • 文件 owership(归属)和 permissions(权限)
      • 文件大小 时间
      • Block 列表[偏移量]:即一个完整文件有哪些 block
      • metadata 存储到磁盘文件名为”fsimage”的镜像文件
      • Block 的位置信息不会保存到 fsimage
      • edits 记录对 metadata 的操作日志
  • secondary name node
    • 整理 fsimage和 edites 日志 得到最新fsimage
      • 避免nn重启后重新汇集所有文件meta信息
    • SNN执行合并时间和机制
      • 根据配置文件设置的时间间隔 fs.checkpoint.period默认3600秒
      • 根据配置文件设置 edits log 大小 fs.checkpoint.size 规定 edits 文件的最大值默认是 64MB
  • data node 从节点
    • 存储block
    • 启动DN线程的时候会向NameNode汇报block位置信息
    • 通过向NN发送心跳保持与其联系(3秒一次),如果NN10分钟没有收到 DN 的心跳,则认为其已经 lost,并 copy 其上的 block 到其它 DN

存储模型block

  • 偏移量标记位置
  • 块大小默认hadoop1.x 是64M,hadoop2.x是128M(物理暂用空间按实际文件大小不会浪费)
  • 默认情况下每个block 都有2个副本共3个副本
  • 副本数不大于节点数
  • 存放策略

存储方式

  • 按大小被切分成若干个 block ,存储到不同节点上

  • 放置策略

    • 第一个副本:放置在上传文件的DN;如果是集群外提交,则随
    • 第二个副本:放置在于第一个副本不同的机架的节点上。
    • 第三个副本:与第二个副本相同机架的不同节点。
    • 更多副本:随机节点

内含机制

  • 心跳
  • 负载均衡
  • 多副本

Why?


分布式

  • 容错
  • 突破单机性能
  • 效率高
  • 可扩展

优点

  • 分布式的特性:
    • 适合大数据处理:GB 、TB 、甚至 PB 级及以上的数据
    • 百万规模以上的文件数量:10K+ 节点。
    • 适合批处理:移动计算而非数据(MR),数据位置暴露给计算框架
  • 自身特性:
    • 可构建在廉价机器上:
    • 高可靠性:通过多副本提提高
    • 高容错性:数据自动保存多个副本;副本丢失后,自动恢复,提供 了恢复机制

缺点

  • 低延迟高数据吞吐访问问题
    • 比如不支持毫秒级
    • 吞吐量大但有限制于其延迟
  • 小文件存取占用 NameNode 大量内存(寻道时间超过读取时间 (99%))
  • 不支持文件修改:一个文件只能有一个写者(深入)

How?


HDFS 读文件流程

  • 通过拓扑网络寻找最近的节点
  1. 首先调用 FileSystem 对象的 open 方法,其实是一个 DistributedFileSystem 的实例。
  2. DistributedFileSystem 通过 rpc 协议获得文件的第 一批 block 的 locations 地址,(同一个 block 按照重复数 会返回多个 locations,因为同一文件的 block 分布式存储 在不同节点上),这些 locations 按照 hadoop 拓扑结构排 序,距离客户端近的排在前面(就近原则选择)。
  3. 前两步会返回一个 FSDataInputStream 对象,该对象 会被封装 DFSInputStream 对象,DFSInputStream 可以方便 的管理 datanode 和 namenode 数据流。客户端调用 read 方 法,DFSInputStream 最会找出离客户端最近的 datanode 并连接。
  4. 数据从 datanode 源源不断的流向客户端。 这些操作对客户端来说是透明的,客户端的角度看来只 是读一个持续不断的流。
  5. 如果第一批 block 都读完了,DFSInputStream 就会去namenode 拿下一批 block的locations,然后继续读,如 果所有的块都读完,这时就会关闭掉所有的流。如果在读数据的时候, DFSInputStream 和 datanode 的通讯发生异常,就会尝试正在读的 block 的排序第二近的 datanode,并且会记录哪个 datanode 发生错误,剩余的 blocks 读的时候就会直接跳过该 datanode。 DFSInputStream 也会检查 block 数据校验和,如果发现一个 坏的 block,就会先报告到 namenode 节点,然后 DFSInputStream 在其他的 datanode 上读该 block 的镜像。 该设计就是客户端直接连接 datanode 来检索数据并且 namenode 来负责为每一个 block 提供最优的 datanode, namenode 仅仅处理 block location 的请求,这些信息都加 载在 namenode 的内存中,hdfs 通过 datanode 集群可以承受 大量客户端的并发访问。

HDFS 写文件流程

  1. 客户端通过调用 DistributedFileSystem 的 create 方 法创建新文件。
  2. DistributedFileSystem 通过 RPC 调用 namenode 去创 建一个没有 blocks 关联的新文件,创建前, namenode 会做 各种校验,比如文件是否存在,客户端有无权限去创建等。 如果校验通过, namenode 就会记录下新文件,否则就会抛 出IO异常。
  3. 前两步结束后,会返回 FSDataOutputStream 的对象, 与读文件的时候相似,FSDataOutputStream 被封装成 DFSOutputStream。 DFSOutputStream 可以协调 namenode 和 datanode。客户端 开始写数据到 DFSOutputStream,DFSOutputStream 会把数 据切成一个个小的 packet,然后排成队列 data quene。
  4. DataStreamer 会去处理接受 data quene,它先询问 namenode 这个新的 block 最适合存储的在哪几个 datanode 里(比如重复数是3那么就找到3个最适合的 datanode), 把他们排成一个管道pipeline 输出。DataStreamer 把packet按队列输出到管道的第一个 datanode 中,第一个datanode又把packet输出到第二个 datanode中,以此类推。
  5. DFSOutputStream 还有一个对列叫 ack quene,也是 由 packet 组成等待 datanode 的收到响应,当 pipeline 中 的 datanode 都表示已经收到数据的时候,这时 ack quene 才会把对应的 packet 包移除掉。 如果在写的过程中某个 datanode 发生错误,会采取以下几步:
    1. pipeline 被关闭掉;
    2. 为了防止防止丢包。ack quene 里的 packet 会同步 到 data quene 里;创建新的 pipeline 管道怼到其他正常 DN 上
    3. 剩下的部分被写到剩下的两个正常的 datanode 中;
    4. namenode 找到另外的 datanode 去创建这个块的复 制。当然,这些操作对客户端来说是无感知的。
  6. 客户端完成写数据后调用 close 方法关闭写入流。

深入 DFSOutputStream 内部原理

是否按照block list 顺序读取block 信息?

多节点并行读,单节点串读?

安装


http://hadoop.apache.org/docs/r2.5.2/hadoop-project-dist/hadoop-common/SingleCluster.html

必备:

  • java
  • ssh

检查:

  • echo JAVA_HOME
  • ssh免密钥设置参照我的VMWare虚拟机笔记中的配置
  • 防火墙是否关闭service iptables status
  • 时间同步软件是否安装

下载

http://www.apache.org/dyn/closer.cgi/hadoop/common/

下载至目录 /opt/soft

解压

tar zxvf hadoop-2.5.1_x64.tar.gz

修改配置

  • cd /opt/soft/hadoop-2.5.1

  • vi etc/hadoop/hadoop-env.sh

    • export JAVA_HOME=/opt/soft/jdk1.7.0_25将jdk变量指向自己的jdk路径,保存退出
  • mkdir data

  • vi etc/hadoop/core-site.xml添加下列配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <configuration>
    <property>
    <name>fs.defaultFS</name>
    <value>hdfs://sj-node1:9000</value>
    </property>
    <property>
    <name>hadoop.tmp.dir</name>
    <value>/opt/soft/hadoop-2.5.1/data</value>
    </property>
    </configuration>

  • vi ./etc/hadoop/hdfs-site.xml

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <configuration>
    <property>
    <name>dfs.replication</name>
    <value>3</value>
    </property>
    <property>
    <name>dfs.namenode.secondary.http-address</name>
    <value>sj-node2:50090</value>
    </property>
    <property>
    <name>dfs.namenode.secondary.https-address</name>
    <value>sj-node2:50091</value>
    </property>
    </configuration>

  • 修改slavesvi ./etc/hadoop/slaves

  • 新建masters文件vi ./etc/hadoop/masters以sj-node2作为第二主机

将配置好的传到其它节点

  • [root@sj-node1 soft]# scp -r hadoop-2.5.1 sj-node2:/opt/soft/
  • [root@sj-node1 soft]# scp -r hadoop-2.5.1 sj-node3:/opt/soft/
  • [root@sj-node1 soft]# scp -r hadoop-2.5.1 sj-node4:/opt/soft/

格式化NN

[root@sj-node1 hadoop-2.5.1]# bin/hdfs namenode -format 只需在NN几点也就是sj-node1上执行,确认没有错误,data目录下有文件生成

启动

[root@sj-node1 hadoop-2.5.1]# sbin/start-dfs.sh 注意检查启动的时候控制台有没有报错

启动后检查访问web

  • 命令行检查
    • hdfs haadmin -getServiceState nn1 hdfs haadmin -getServiceState nn2

    • NN主节点 http://192.168.199.101:50070/

    • SNN http://192.168.199.102:50090/status.html

    • 目录访问http://192.168.199.101:50070/explorer.html#/

命令测试

  • 创建文件夹
    • bin/hadoop fs -mkdir /testdir
  • 上传文件
    • [root@sj-node1 hadoop-2.5.1]# bin/hadoop fs -put README.txt /testdir