Hadoop 🐘

HDFS, Map-Reduce, HBase

组成

  1. common: 辅助工具
  2. HDFS: 数据存储
  3. Yarn: 资源调度
  4. MapReduce: 数据计算

HDFS

  1. namenode: 存储文件的元数据,内存占用大
  2. datanode: 本地文件系统存储文件的块数据与块数据的校验和信息
  3. secondarynamenode: 监控 hdfs 状态的辅助后台程序

YARN

resource manager:

  1. 处理客户端请求
  2. 监控 node manager 状态
  3. 资源分配与调度

node manager:

  1. 管理单个 node 的资源
  2. 处理 resource manager 的命令
  3. 处理 applicationMaster 的命令

application Master:

  1. 切分数据
  2. 申请资源并分配给 node 内部的任务
  3. 任务监控与容错处理

container: yarn 中对所有资源的抽象

Map Reduce

  1. map: 并行处理数据
  2. reduce: 对 map 处理结果汇总

单机 demo

input 与 output : hadoop 集群跑起来以后, 就对应 HDFS 路径而不是主机路径

mkdir input #input里放些文件
# 统计 dfs 开头的单词个数
hadoop-3.2.0/bin/hadoop jar hadoop-3.2.0/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.2.0.jar grep input/ output 'dfs[a-z.]+'

# 统计单词出现次数
hadoop-3.2.0/bin/hadoop jar hadoop-3.2.0/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.2.0.jar wordcount winput/ output

配置

# namenode resourcemanager secondarynamenode 3个占用内存大的不要放一台机器
192.168.142.88: namenode datanode nodemanager
192.168.142.89: datanode resourcemanager nodemanager
192.168.142.90: datanode secondarynamenode nodemanager

ssh

集群场景下 namenode 和 resourcemanager 所在节点需要负责整个集群环境公钥的分发, 否则 HDFS 数据无法同步, namenode 所在机器的 root 用户也需要分发公钥 /etc/hosts 配置好每个机器的 ip hostname : 大坑 datanode 一直注册不上原来是这个问题

hadoop/etc/hadoop

core-site.xml

    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://192.168.142.88:9000</value>
    </property>

    <property>
        <name>hadoop.tmp.dir</name>
        <value>/home/battery/hadoop/tmp</value>
    </property>

hadoop-env.sh 指定 java_home 位置:

export JAVA_HOME=xxxxx

hdfs-site.xml 配置 hdfs 副本数量, 默认 3:

    <property>
        <name>dfs.replication</name>
        <value>3</value>
    </property>
    <!--指定secondary node位置, secondary node不要和name node放在一台机器上-->
    <property>
        <name>dfs.namenode.secondary.http-address</name>
        <value>192.168.142.90:50090</value>
    </property>

启动HDFS, 第一次启动格式化一下 namenode, 以后不要, 初次格式化 namenode 与 datanode cluster-id 一致,namenode 与 datanode 依赖 cluster-id 通信, 再次格式化 namenode 生成不一致的 cluster-id

bin/hdfs namenode -format

启动 namenode 和 datanode

# 已废弃
sbin/hadoop-daemon.sh start namenode
sbin/hadoop-daemon.sh start datanode
# 新的方式
bin/hdfs --daemon start namenode/datanode

web 页面:

3.x 版本默认端口由50070变为: 9870

hadoop

HDFS

创建路径:

bin/hdfs dfs -mkdir -p /usr/man/input

hdfs

拷贝本地文件到 HDFS 中(依赖 core-site.xml 中 fs 的配置):

# 本地文件 目标HDFS路径
bin/hdfs dfs -put 本地文件 /usr/man/input

hdfs

block size : 块 最大大小, 可以修改配置

YARN

yarn-env.sh 指定 java_home 位置:

export JAVA_HOME=XXXXX

yarn-site.xml :

    <property>
        <name>yarn.nodemanager.aux-services</name>
        <value>mapreduce_shuffle</value>
    </property>
    <!--resource manager尽量不要和namenode secondarynode放在一起-->
    <!--resource manager在哪个机器 就先启动这台机器上的yarn服务-->
    <property>
        <name>yarn.resourcemanager.hostname</name>
        <value>192.168.142.89</value>
    </property>

    <!--ip为各自节点的ip-->
    <property>
        <name>yarn.nodemanager.hostname</name>
        <value>192.168.142.88</value>
    </property>

找不到 org.apache.hadoop.mapreduce.v2.app.MRAppMaster 错误:

hadoop classpath

# classpath内容设置到yarn-site.xml中

yarn-site.xml :

    <property>
        <name>yarn.application.classpath</name>
        <value>/home/battery/hadoop/etc/hadoop:/home/battery/hadoop/share/hadoop/common/lib/*:/home/battery/hadoop/share/hadoop/common/*:/home/battery/hadoop/share/hadoop/hdfs:/home/battery/hadoop/share/hadoop/hdfs/lib/*:/home/battery/hadoop/share/hadoop/hdfs/*:/home/battery/hadoop/share/hadoop/mapreduce/lib/*:/home/battery/hadoop/share/hadoop/mapreduce/*:/home/battery/hadoop/share/hadoop/yarn:/home/battery/hadoop/share/hadoop/yarn/lib/*:/home/battery/hadoop/share/hadoop/yarn/*</value>
    </property>

Map-Reduce

mapred-env.sh 指定 java_home:

export JAVA_HOME=XXXX

mapred-site.xml 指定 map-reduce 运行在 yarn 中:

    <property>
      <name>mapreduce.framework.name</name>
      <value>yarn</value>
    </property>

启动服务, 默认端口 8088:

bin/yarn --daemon start resourcemanager
bin/yarn --daemon start nodemanager

map-reduce 任务监控:

Map-Reduce

mapred-site.xml 配置 job history 记录:

    <!--配置为集群各节点自己的ip-->
    <property>
        <name>mapreduce.jobhistory.address</name>
        <value>192.168.142.88:10020</value>
     </property>
    <property>
        <name>mapreduce.jobhistory.webapp.address</name>
        <value>192.168.142.88:19888</value>
    </property>

启动 history 监控服务:

mapred --daemon start historyserver

job history

日志聚合

yarn-site 中配置 log-aggregation:

    <property>
        <name>yarn.log-aggregation-enable</name>
        <value>true</value>
    </property>
    <property>
        <name>yarn.log-aggregation.retain-seconds</name>
        <value>60480</value>
    </property>

开启 log-aggre 后, 整个服务需要重启,会记录下 map-reduce 执行的详细日志信息

log

集群启动验证

在 192.168.142.89 上 hdfs 拷贝文件, 在 192.168.142.88 节点上查看文件

hdfs dfs -put winput /

集群


HDFS

128M 块大小

hadoop fs .... hdfs dfs .... : dfs 是 fs 的实现类

命令:

-setrep 3 # 设置副本数量

java 客户端操作:

resources 目录下可以放 hadoop 的配置文件, 优先级高于 hadoop 中的配置

FileSystem

fs.copyFromLocalFile();//上传
fs.copyToLocalFile();//下载
fs.delete();//删除
fs.rename();//重命名
fs.listFiles();//查看文件信息
fs.listStatus();//判断文件是文件还是文件夹
IOUtils.copyBytes();//流拷贝
FsDataInputStream.seek(); //移动文件读写指针

namenode 存储文件 metadata 元数据 ,负责管控客户端具体向哪些 datanode 读写数据, 优先选择离客户端网络拓扑结构最近的节点

namenode 服务运行时数据工作在内存中, FsImage 会向磁盘备份, Edits 文件只追加记录, 记录 namenode 元数据变化, 靠 FsImage 和 Edits, 每次服务重启都可以保证 namenode 数据不丢失, secondarynamenode 负责 FsImage 和 Edits 的合并(定时时间到了, Edits 满了). checkpoint 触发合并事件,需要 hdfs-site 配置.

集群刚启动时, 初始一段时间 namenode 需要加载数据, 这段时间处于安全模式, 数据只读. 满足最小副本条件(至少 1 个副本)后退出安全模式

datanode 每小时向 namenode 上送一次信息, 3 秒一次心跳, 心跳返回信息带有 namenode 给 datanode 的命令, namenode 超过 10 分钟+30 秒(超时时间可以设置)收不到心跳就认为 datanode 挂掉, 心跳超时时间设置: heartbeat

数据完整性校验:

datanode 每个数据块都进行 crc 校验

小文件归档:

hadoop archive -archiveName xxx.har -p /input /output

Map-Reduce

  1. Map 切分数据 <K,V> 继承 Mapper<输入数据 key 的类型,输入数据的类型,输出 key 的类型,输出数据的类型>, 重写 map 方法

  2. Reduce 按 key 汇总数据 继承 Reducer,重写 reduce 方法

  3. Driver

    Configuration cfg=new Configuration();
    //获取Job
     Job job=Job.getInstance(cfg);
     job.setJarByClass(xxxDriver.class);
     //关联map reduce
     job.setMapperClass(xxxxMapper.class);
     job.setReducerClass(xxxReducer.class);
     //设置输出数据类型
     job.setMapperOutputKeyClass(xxx.class);
     job.setMapperOutputValueClass(xxx.class);
     job.setOutputKeyClass(xxx.class);
     job.setOutputValueClass(xxx.class);
     //设置文件输入/输出路径
     FileInputFormat.setInputPaths(job,new Path(xxxx));
     FileOutputFormat.setOutputPaths(job,new Path(xxxx));
     //提交job作业
     job.waitForCompletion(true);
    
上次更新: 4 个月前