HDFS文件系统
HDFS是一个分布式文件系统,采用分而治之的设计思想,将大文件、大批量文件,分布式存放在大量服务器上,为各类分布式运算框架(MapReduce,spark,tez等)提供数据存储服务。首先,它是一个文件系统,用于存储文件,通过统一的命名空间目录树来定位文件,对用户来说,DataNode是透明的,HDFS相当于是提供了一个统一的目录结构,用户上传的文件的适合,只需要和这个统一的目录结构打交道,虽然实际上用户的文件被切成不同的block存放在了不同的DataNode上,这部分元信息被存放在NameNode中;其次,它是分布式的,由很多服务器联合起来实现其功能,集群中的服务器有各自的角色。
基本特性
适合用来做数据分析,并不适合用来做网盘应用,因为,不便修改,延迟大,网络开销大,成本太高
- HDFS中的文件在物理上是分块存储(block),块的大小可以通过配置参数(dfs.blocksize)来规定,默认大小在hadoop2.x版本中是128M,老版本中是64M;
- HDFS文件系统会给客户端提供一个统一的抽象目录树,客户端通过路径来访问文件,形如:hdfs://namenode:port/dir-a/dir-b/dir-c/file.data;
- 目录结构及文件分块信息(元数据)的管理由NameNode节点承担。NameNode是HDFS集群主节点,负责维护整个hdfs文件系统的目录树,以及每一个路径(文件)所对应的block块信息(block的id,及所在的DataNode服务器);
- 文件的各个block的存储管理由DataNode节点承担。DataNode是HDFS集群从节点,每一个block都可以在多个DataNode上存储多个副本(副本数量也可以通过参数设置dfs.replication);
- HDFS是设计成适应一次写入,多次读出的场景,且不支持文件的修改;
常见命令
// 列出文件
hadoop fs -ls /
// 创建目录
hadoop fs -mkdir 目录名称
// 查看文件
hadoop fs -cat 文件名称
// 删除文件或文件夹
hadoop fs -rm -r /aaa/bbb/
// 从本地文件系统中拷贝文件到hdfs路径去
hadoop fs -copyFromLocal ./jdk.tar.gz /aaa/
// 上传,等同于copyFromLocal
hadoop fs -put /aaa/jdk.tar.gz /bbb/jdk.tar.gz.2
// 从hdfs拷贝到本地
hadoop fs -copyToLocal /aaa/jdk.tar.gz
// 从hdfs下载文件到本地,等同于copyToLocal
hadoop fs -get /aaa/jdk.tar.gz
// 统计文件系统的可用空间信息
hadoop fs -df -h /
// 统计文件夹的大小信息
hadoop fs -du -s -h /aaa/*
// 统计一个指定目录下的文件节点数量
hadoop fs -count /aaa/
// 设置hdfs中文件的副本数量,这里设置的副本数只是记录在NameNode的元数据中,是否真的会有这么多副本,还得看DataNode的数量
hadoop fs -setrep 3 /aaa/jdk.tar.gz
常用参数
hdfs-site.xml
// 每个block块的大小,默认128M
dfs.blocksize
// 文件副本个数
dfs.replication
工作机制
- HDFS集群分为两大角色:NameNode、DataNode;
- NameNode负责管理整个文件系统的元数据;
- DataNode负责管理用户的文件数据块;
- 文件会按照固定的大小(blocksize)切成若干块后分布式存储在若干台DataNode上;
- 每一个文件块可以有多个副本,并存放在不同的DataNode上;
- DataNode会定期向NameNode汇报自身所保存的文件block信息,而NameNode则会负责保持文件的副本数量;
- HDFS的内部工作机制对客户端保持透明,客户端请求访问HDFS都是通过向NameNode申请来进行;
NameNode机制
NameNode职责:负责客户端请求的响应;元数据的管理(查询,修改);
NameNode对数据的管理采用了三种存储形式:
- 内存元数据(NameSystem);
- 磁盘元数据镜像文件;
- 数据操作日志文件(可通过日志运算出元数据);
元数据管理机制
- 内存中有一份完整的元数据:内存meta data;
- 磁盘有一个“准完整”的元数据镜像:fsimage,文件存在于NameNode的工作目录中;
- 用于衔接内存metadata和持久化元数据镜像fsimage之间的操作日志:edits文件,当客户端对HDFS中的文件进行新增或者修改操作,操作记录首先被记入edits日志文件中,当客户端操作成功后,相应的元数据会更新到内存meta.data中;
元数据checkpoint
每隔一段时间,会由SecondaryNameNode将NameNode上积累的所有edits和一个最新的fsimage下载到本地,并加载到内存进行merge,这个过程称为checkpoint。
NameNode和SecondaryNameNode的工作目录存储结构完全相同,所以,当NameNode故障退出需要重新恢复时,可以从SecondaryNameNode的工作目录中将fsimage拷贝到NameNode的工作目录,以恢复NameNode的元数据。
checkpoint参数
dfs.namenode.checkpoint.check.period=60 #检查触发条件是否满足的频率,60秒
dfs.namenode.checkpoint.dir=file://${hadoop.tmp.dir}/dfs/namesecondary
#以上两个参数做checkpoint操作时,secondary namenode的本地工作目录
dfs.namenode.checkpoint.edits.dir=${dfs.namenode.checkpoint.dir}
dfs.namenode.checkpoint.max-retries=3 #最大重试次数
dfs.namenode.checkpoint.period=3600 #两次checkpoint之间的时间间隔3600秒
dfs.namenode.checkpoint.txns=1000000 #两次checkpoint之间最大的操作记录
DataNode机制
Datanode工作职责:存储管理用户的文件块数据;定期向NameNode汇报自身所持有的block信息(通过心跳信息上报),这点很重要,因为当集群中发生某些block副本失效时,集群如何恢复block初始副本数量的问题。
<property>
<name>dfs.blockreport.intervalMsec</name>
<value>3600000</value>
<description>Determines block reporting interval in milliseconds.</description>
</property>
DataNode掉线判断时限参数
DataNode进程死亡或者网络故障造成DataNode无法与NameNode通信,NameNode不会立即把该节点判定为死亡,要经过一段时间,这段时间暂称作超时时长。HDFS默认的超时时长为10分钟+30秒。如果定义超时时间为timeout,则超时时长的计算公式为:
timeout = 2 * heartbeat.recheck.interval + 10 * dfs.heartbeat.interval
而默认的heartbeat.recheck.interval 大小为5分钟,dfs.heartbeat.interval默认为3秒。
需要注意的是hdfs-site.xml 配置文件中的heartbeat.recheck.interval的单位为毫秒,dfs.heartbeat.interval的单位为秒。所以,举个例子,如果heartbeat.recheck.interval设置为5000(毫秒),dfs.heartbeat.interval设置为3(秒,默认),则总的超时时间为40秒。
<property>
<name>heartbeat.recheck.interval</name>
<value>2000</value>
</property>
<property>
<name>dfs.heartbeat.interval</name>
<value>1</value>
</property>
文件上传机制
用户上传的文件,被切成诺干个block块存放在不同的DataNode中,并且每个文件都会在集群中存储多个文件副本,副本的数量可以由用户指定。至于文件被切成多少个block快,每个块在哪台DataNode上,这部分元信息存储在NameNode中。
客户端要向HDFS写数据,首先要跟NameNode通信以确认可以写文件并获得接收文件block的DataNode,然后,客户端按顺序将文件逐个block传递给相应DataNode,并由接收到block的DataNode负责向其他DataNode复制block的副本。
- 根NameNode通信请求上传文件,NameNode检查目标文件是否已存在,父目录是否存在;
- NameNode返回是否可以上传;
- client请求第一个block该传输到哪些datanode服务器上;
- NameNode返回3个DataNode服务器ABC;
- client请求3台dn中的一台A上传数据(本质上是一个RPC调用,建立pipeline),A收到请求会继续调用B,然后B调用C,将真个pipeline建立完成,逐级返回客户端;
- client开始往A上传第一个block(先从磁盘读取数据放到一个本地内存缓存),以packet为单位,A收到一个packet就会传给B,B传给C;A每传一个packet会放入一个应答队列等待应答;
- 当一个block传输完成之后,client再次请求NameNode上传第二个block的服务器;
文件下载机制
客户端将要读取的文件路径发送给NameNode,NameNode获取文件的元信息(主要是block的存放位置信息)返回给客户端,客户端根据返回的信息找到相应DataNode逐个获取文件的block并在客户端本地进行数据追加合并从而获得整个文件。
- 跟NameNode通信查询元数据,找到文件块所在的DataNode服务器;
- 挑选一台DataNode(就近原则,然后随机)服务器,请求建立socket流;
- DataNode开始发送数据(从磁盘里面读取数据放入流,以packet为单位来做校验);
- 客户端以packet为单位接收,现在本地缓存,然后写入目标文件;
HDFS客户端编程场景
- 数据采集
YARN
运算资源调度。
MapReduce程序应该是在很多机器上并行启动,而且先执行MapTask,当众多的MapTask都处理完自己的数据后,还需要启动众多的ReduceTask,这个过程如果用用户自己手动调度不太现实,需要一个自动化的调度平台,hadoop中就为运行MapReduce之类的分布式运算程序开发了一个自动化调度平台:YARN。
YARN集群中有两个角色:1台 ResourceManager 和 N台 NodeManager。ResourceManager一般安装在一台专门的机器上,NodeManager应该与HDFS中的DataNode重叠在一起。
yarn-site.xml
<property>
<name>yarn.resourcemanager.hostname</name>
<value>hdp-04</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
Linux环境准备
接下来主要介绍Hadoop集群环境的搭建过程,实际应用中应该不会这样做,而是通过一些管理工具进行安装,比如可视化安装:Ambari。
前置条件
CentOS7
Oracle VM VirtualBox
安装过程
这就相当于通过虚拟机搭建一个局域网,安装配置过程已经截图并整理成PPT。主要需要注意的地方就是网络的配置,我这里通过配置两个网卡来实现:一个用于访问外部网络(NAT);一个用于和window主机交互(Host-Only)。
我的系统是centos7
vi /etc/sysconfig/network-scripts/ifcfg-enp0s3
配置文件修改成以下内容
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=static
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
NAME=enp0s3
UUID=4704faea-0e23-4ad9-a06c-3e37e577636c
DEVICE=enp0s3
ONBOOT=yes
NM_CONTROLLED=yes
IPADDR=192.168.88.21
虚拟机安装过程
基础配置
添加用户
分别在三台服务器上执行创建 haddop用户,同时设置密码为hadoop
useradd hadoop
passwd hadoop
创建用户之后切换为hadoop用户登录,我们所有的操作都基于hadoop用户
配置host
分别在三台服务器配置host
vi /etc/hosts
添加以下内容
192.168.88.21 master
192.168.88.22 slave1
192.168.88.23 slave2
配置免密登录
分别在三台机器上安装 openssh-server
yum install openssh-server
分别在三台机器上执行以下命令
mkdir .ssh
chmod 700 .ssh
ssh-keygen -t rsa
cp id_rsa.pub authorized_keys
chmod 600 authorized_keys
在 22 服务器执行
scp /home/hadoop/.ssh/id_rsa.pub hadoop@master:/home/hadoop/.ssh/id_rsa.pub.slave1
在 23 服务器执行
scp /home/hadoop/.ssh/id_rsa.pub hadoop@master:/home/hadoop/.ssh/id_rsa.pub.slave2
在 21 服务器执行
cat id_rsa.pub.slave1 >> authorized_keys
cat id_rsa.pub.slave2 >> authorized_keys
scp /home/hadoop/.ssh/authorized_keys hadoop@slave1:/home/hadoop/.ssh/authorized_keys
scp /home/hadoop/.ssh/authorized_keys hadoop@slave2:/home/hadoop/.ssh/authorized_keys
至此配置完成,接下来是测试:
在 21 服务器执行
ssh salve1
ssh salve2
有个问题,之前配置好了之后还是不停提示要输入密钥,然后安装了 openssh-server 之后,再测试就可以了,不知道是不是这个的影响。
配置JDK
jdk-8u171-linux-x64.tar.gz
在/home/hadoop 目录下创建java文件夹
mkdir java
在java 目录内解压安装包
tar -zxvf jdk-8u171-linux-x64.tar.gz
然后分别拷贝到两台slave
scr -r jdk1.8 hadoop@slave1:/home/hadoop
scr -r jdk1.8 hadoop@slave2:/home/hadoop
分别在三台机器上配置JAVA_HOME
export JAVA_HOME=/home/hadoop/jdk1.8
export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar
:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin
测试:
执行 java -version 看控制台输出
其它配置
修改windos下的hosts文件,因为到时候再浏览器上访问的时候会用到域名
C:\WINDOWS\System32\drivers\etc\hosts
192.168.88.21 master
192.168.88.22 slave1
192.168.88.23 slave2
修改linux系统的hostname,注意不是修改/etc/hoss文件,centos7永久修改hostname使用以下命令
hostnamectl set-hostname 名称
安装Hadoop
下载安装
1、官网下载,这个地址下载有点慢
2、以下的地址下载更快一些
http://mirror.bit.edu.cn/apache/
http://mirror.bit.edu.cn/apache/
https://mirrors.tuna.tsinghua.edu.cn/apache/
我最终下载的版本是:hadoop-2.7.6.tar.gz
安装过程很简单,只需要直接解压就可以了。
三台机器机器最终的配置基本一样,所以我们只需要在一台机器上配置好,然后拷贝到其它机器就好, 这里是在master机器上配置。
在master上执行以下命令
cd /home/Hadoop
mkdir -p cludata/hadoop
cd cludata/hadoop
mkdir -p hdfs/data hdfs/name temp
tar -zxvf hadoop-2.7.6.tar.gz
HADOOP_HOME
就是配置hadoop环境变量,这个需要在三台机器上分别执行
vi ~/.bash_profile
export HADOOP_HOME=/home/hadoop/hadoop-2.7.6
export PATH=$PATH:$JAVA_HOME/bin::$HADOOP_HOME/bin:$HADOOP_HOME/sbin
配置文件
主要需要配置以下几个配置文件:core-site.xml、hdfs-site.xml、mapred-site.xml和yarn-site.xml、slaves。然后可能还需要再hadoop-env.sh中添加JAVA环境变量。
以下配置文件可作为参考,还有很多其它配置项。
- core-site.xml
该配置文件主要用于定义系统级别的参数,如HDFS、URL、hadoop的临时目录
<configuration>
<property>
<name>fs.default.name</name>
<value>hdfs://master:9000</value>
<description>文件系统主机和端口</description>
</property>
<property>
<name>io.file.buffer.size</name>
<value>131072</value>
<description>每个block的大小</description>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>file:/home/hadoop/cludata/hadoop/temp</value>
<description>临时目录</description>
</property>
</configuration>
- dfs-site.xml
<configuration>
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>master:9001</value>
<description>通过web界面来查看HDFS状态</description>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:/home/hadoop/cludata/hadoop/hdfs/name</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>file:/home/hadoop/cludata/hadoop/hdfs/data</value>
</property>
<property>
<name>dfs.replication</name>
<value>3</value>
<description>每个Block有2个备份</description>
</property>
<property>
<name>dfs.webhdfs.enabled</name>
<value>true</value>
<description>是否通过http协议访问hdfs文件</description>
</property>
</configuration>
- mapred-site.xml
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<property>
<name>mapreduce.jobhistory.address</name>
<value>master:10020</value>
</property>
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>master:19888</value>
</property>
</configuration>
- yarn-site.xml
<configuration>
<!-- Site specific YARN configuration properties -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.nodemanager.aux-services.mapreduce.shuffle.class</name>
<value>org.apache.hadoop.mapred.ShuffleHandler</value>
</property>
<property>
<name>yarn.resourcemanager.address</name>
<value>master:8032</value>
</property>
<property>
<name>yarn.resourcemanager.scheduler.address</name>
<value>master:8030</value>
</property>
<property>
<name>yarn.resourcemanager.resource-tracker.address</name>
<value>master:8031</value>
</property>
<property>
<name>yarn.resourcemanager.admin.address</name>
<value>master:8033</value>
</property>
<property>
<name>yarn.resourcemanager.webapp.address</name>
<value>master:8088</value>
</property>
<property>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>8192</value>
</property>
</configuration>
- slaves
这个配置文件主要是配置 datanode
把localhost去掉,添加以下内容
slave1
slave2
配置完成之后,将整个hadoop文件夹拷贝到其它两台机器
cd /home/hadoop
scp -r hadoop-2.7.6 hadoop@slave1:/home/hadoop/
scp -r hadoop-2.7.6 hadoop@slave2:/home/hadoop/
格式化
在启动hadoop之前,需要先格式化HDFS文件系统,只需要在master上执行即可
hadoop namenode -format
启动
有关于hadoop的一些脚本命令,存放在根目录下的sbin 文件夹下:即/home/hadoop /hadoop-2.7.6/sbin
所以,先进入sbin目录
cd /home/hadoop /hadoop-2.7.6/sbin
- 启动NameNode
hadoop-daemon.sh start namenode
执行该命令后可以通过 ps -ef|grep hadoop 命令查看hadoop进程,也可以使用jsp命令查看JVM进行。运行jsp命令之后,可以可能到 Namenode进程。
- 启动DataNode
hadoop-daemon.sh start datanode
在master上执行该命令后,在两台slave上分别执行 jps 命令查看 datanode是否启动,如果发现 Datanode 进程说明启动成功。
提示:其实以上两个启动过程可以通过一个脚本来启动,hadoop里面也提供了这个脚本,也是在sbin目录中,只要执行这个脚本就可以了
./start-dfs.sh
//对应的停止命令
./stop-dfs.sh
- 启动ResourceManager
yarn-daemon.sh start resourcemanager
执行该命令之后,使用jsp命令可以查看到ResourceManager说明启动成功。
- 启动NodeManager
yarn-daemon.sh start nodemanager
同理,通过jpps命令可以看到 NodeManage进程。
注意:以上两个过程也可以通过一个脚本来启动
./start-yarn.sh
//对应的停止命令
./stop-yarn.sh
- 浏览器访问
可以看到以下界面
可以看到以下界面
常见命令
hadoop下有一些常见命令
列出文件:hadoop fs -ls /
创建目录:hadoop fs -mkdir 目录
上传文件:hadoop fs -put filename 目录
查看文件:hadoop fs -cat 文件
测试案例
启动之后,可以用hadoop来处理一个demo,这个demo程序是hadoop在安装包里面已经提供了。
hadoop jar /home/hadoop/hadoop-2.7.6/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.6.jar pi 5 10
Pi 5 10 表示开 5个Map , 10 个 Reduce
执行这命令之后,控制台会有一系列输出,同时在浏览器上也可以看到效果
MapReducer
其实上面就是一个Map Reducer 程序,这是官方提供的一个Demo,不过我们好像并不是很清楚这个程序的运行机制是什么样的,所以在此之前,有必要了解一下MapReducer。MapReducer可以在任何地方运行程序,访问HDFS上的文件并进行统计运算,并且可以把统计的结果写回HDFS的结果文件中。包括接下来介绍了HIVE,其实内部也是基于MapReducer实现,只不过HIVE内部进行了大量封装,所以我们才可以写SQL语句,其实每条SQL语句,都可以看成是一个MapReducer程序。MapReducer中有两个概念:Map 和 Reducer。
Map阶段: 将每一行文本数据变成<单词,1>这样的kv数据
Reduce阶段:将相同单词的一组kv数据进行聚合:累加所有的v
下面是一个简单WordCount 示例
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.hand.sxy</groupId>
<artifactId>MapReducer</artifactId>
<version>1.0</version>
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.7.6</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-mapreduce-client-core</artifactId>
<version>2.7.6</version>
</dependency>
</dependencies>
</project>
WordCount.java
package com.hand.sxy;
import com.hand.sxy.utils.FileUtil;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import java.io.IOException;
import java.util.Iterator;
import java.util.StringTokenizer;
public class WordCount {
public static void main(String[] args) throws Exception {
FileUtil.deleteDir("/output");
Configuration conf = new Configuration();
String[] otherArgs = new String[]{"hdfs://master:9000/test/dream.txt", "/output"};
if (otherArgs.length != 2) {
System.err.println("Usage:Merge and duplicate removal <in> <out>");
System.exit(2);
}
Job job = Job.getInstance(conf, "WordCount");
job.setJarByClass(WordCount.class);
job.setMapperClass(WordCount.TokenizerMapper.class);
job.setReducerClass(WordCount.IntSumReduce.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
FileInputFormat.addInputPath(job, new Path(otherArgs[0]));
FileOutputFormat.setOutputPath(job, new Path(otherArgs[1]));
System.exit(job.waitForCompletion(true) ? 0 : 1);
}
public static class TokenizerMapper extends Mapper<Object, Text, Text, IntWritable> {
public static final IntWritable one = new IntWritable(1);
private Text word = new Text();
public void map(Object key, Text value, Context context) throws IOException, InterruptedException {
StringTokenizer itr = new StringTokenizer(value.toString());
while (itr.hasMoreTokens()) {
this.word.set(itr.nextToken());
context.write(this.word, one);
}
}
}
public static class IntSumReduce extends Reducer<Text, IntWritable, Text, IntWritable> {
private IntWritable result = new IntWritable();
public void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
int sum = 0;
IntWritable val;
for (Iterator i = values.iterator(); i.hasNext(); sum += val.get()) {
val = (IntWritable) i.next();
}
this.result.set(sum);
context.write(key, this.result);
}
}
}
这里面就涉及到了一些API,这个可以自己去网上查,这里不做过多介绍。
接下来需要做的就是执行这个程序,首先,将这个程序打包成jar,然后上传服务器
mvn clen install
在hdfs系统上准备好数据,编辑 dream.txt 文件内容如下
Hello bob
I am good
How are you
I am fine
Good good study
上传dream.txt到hdfs系统
hadoop fs -mkdit /test
hadoop fs -put dream.txt /test/dream.txt
执行MapReducer-1.0.jar程序
hadoop jar MapReducer-1.0.jar com.hand.sxy.WordCount
在控制台和浏览器上观察
浏览器打开:http://master:8088/cluster/apps
浏览器打开:http://master:50070/explorer.html#/output
程序结果即在hsfs中的 /output/part-r-00000文件中
hadoop fs -cat /output/part-r-00000
输出的就是每个单词出现的次数,这就是一个最简单的MapReducer程序。
HA集群
hadoop的HA集群,即hadoop的高可用集群配置,为了解决hadoop中的NameNode单点故障问题。这个配置的时候比较繁琐,有空再补上
安装HIVE
HIVE是在MapReducer上的一层封装,通过写sql方式来实现MapReducer程序。什么意思?就是说大部分情况下,有了HIVE之后,不需要再开发MapReducer程序了,直接写HQL即可,大大节约了时间成本。HIVE非常强大,在创建hie表的时候,字段类型用的是java里面的数据类型,连Map类型都可以用,很强大。
下载安装
http://mirror.bit.edu.cn/apache/hive/
http://mirrors.hust.edu.cn/apache/hive/
http://mirrors.shu.edu.cn/apache/hive/
http://mirrors.tuna.tsinghua.edu.cn/apache/hive/
安装位置随便安装到那台机器都都可以,先解压
tax -zxvf apache-hive-1.2.2-bin.tar.gz
6.2. 配置文件
添加一个hive-site.xml配置文件
<configuration>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://centos81:3306/hive?
createDatabaseIfNotExist=true</value>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.jdbc.Driver</value>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>root</value>
</property>
</configuration>
这里其实就是配置hive元数据的存放位置,即hive中的数据库名、表名、字段等西信息。其实不配置也没关系, hive默认内置了一个其它 的数据库。
这里选择的是mysql数据库,所以还需要提供一个mysql驱动包,这里是:mysql-connector-java-5.1.46.jar
启动
cd hive-1.2.2
bin/hive
如果你已经安装好了mysql,执行这个命令之后,就会在mysql下创建一个hive数据库。如图:
之后,就可以用一些hive的语法了。
常见命令
和我们的sql非常类似
列出数据库:show databases;
创建数据库:create database 数据库名;
使用数据库:use 数据库 名;
创建数据表:create table 表名 (xxx);
创建外部表:create external table 表名 (xxx);
创建分区表:create external table 表名 (xxx) partitioned by (day string);
配置分隔符:在建表语句后面加 row format delimited fields terminated by ',' ;
测试
在hive中新建数据库和表,并在hadoop中上传文件,看看在hivez怎么通过sql查出来。
create database tsdb;
use tsdb;
create table t_test1(id int,name string,age int) row format delimited fields terminated by ',';
执行以上命令之后,观察在hadoop中hdfs的目录
可以看到,生成了一个和数据库名相同的文件夹子,点进去发现,也生成了一个和表名对应的目录。
vi t_test1.txt
文件内容如下:
1,xiaoyong,20
2,gaoxiao,40
3,liuxin,19
上传这个文件到hdfs
hadoop fs -put t_test1.txt /user/hive/warehouse/tsdb.db/t_test1
在hive控制台查询
select * from t_test1;
[图片上传失败...(image-83e835-1535979338058)]
结果已经查出来了。
这本是一个MapReducer程序做的事情,现在一个SQL就搞定了。Hive中还有很多概念,这里就不做过多结算了。
安装MySQL
这里安装MySQL的目的就一个:保存HIVE中的元数据。在安装MySQL之前,先装一个虚拟机,修改IP,修改四台机器的 /etc/host,这就当作是一台专用数据库服务器。
更新yum源
下载mysql的yum源:
wget -P /home/lisonglin [http://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm](http://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm)
安装mysql的yum源:
rpm -ivh mysql57-community-release-el7-11.noarch.rpm
安装
执行以下命令,然后一直按y就可以了
yum install mysql-community-server
启动测试
启动服务
systemctl start mysqld
通过mysql客户但登录mysql,默认是不需要密码
mysql -uroot
设置密码
set password = passeord(‘root’);
修改配置文件,这里只修改编码集,配置文件默认在 /etc/my.cnf
show variables lie ‘character%’;
vi /etc/my.cnf
[mysql]
default-character-set = utf8
[mysqld]
character_set_server = utf8
常用命令
常见的 启动、停止、重启等命令
启动:systemctl start mysqld
停止:# systemctl stop mysqld
重启:systemctl restart mysqld
设置开机启动:systemctl enable mysqld
查看 MySQL Server 状态:systemctl status mysqld
安装Zookeeper
Zookeeper是一个基础组件,主要功能包括:
可以为客户端管理少量数据,其中在zookeeeper中数据为键值格式。其中key类似于文件目录结构,但不是目录
/aa “valuea”
/aa/cc “valueb”
可以为客户端监听指定数据节点得装填,并在数据节点发生变化时通知客户端。
应用场景:zookeeeper的应用场景可以非常广泛,比如微服务架构中的服务注册中心,用于服务上下线动态感知。zookeeper在hadoop体系中是为了高可用,是为了解决DataNode的单点故障问题;在Hbase中保存了Hbase各个ReginServer和master的信息。
下载安装
生产环境一般是部署zookeeper集群,部署到奇数台服务器,一般3台或者5台。zookeeper有一个投票选举机制,所以有个leader 和 flower概念。
下载地址:http://mirror.bit.edu.cn/apache/zookeeper/zookeeper-3.4.12/
解压:tax -zxvf zookeeper-3.4.12.tar.gz
8.2. 配置文件
cd zookeeper-3.4.12/conf
cp zoo_sample.cfg zoo.cfg
vi zoo.cfg
我的配置文件内容如下:
# The number of milliseconds of each tick
tickTime=2000
# The number of ticks that the initial
# synchronization phase can take
initLimit=10
# The number of ticks that can pass between
# sending a request and getting an acknowledgement
syncLimit=5
# the directory where the snapshot is stored.
# do not use /tmp for storage, /tmp here is just
# example sakes.
dataDir=/home/hadoop/cludata/zkdata
# the port at which the clients will connect
clientPort=2181
# The number of snapshots to retain in dataDir
#autopurge.snapRetainCount=3
# Purge task interval in hours
# Set to "0" to disable auto purge feature
#autopurge.purgeInterval=1
server.21=master:2888:3888
server.22=slave1:2888:3888
server.23=slave2:2888:3888
创建zk数据目录
cd ~
mkdir -p cludata/zkdata
启动
在三台服务器下分别执行以下命令
cd ~/zookeeper-3.4.12/
bin/zkServer.sh start
在启动之后可以查看状态
bin/zkServer.sh status
启动脚本
为了方便启动,提供一个启动脚本
常见命令
进入客户端
cd zookeeper-3.4.12
bin/zkCli.sh
//或者连接到其它服务器
bin/zkCli.sh -server slave1:2181
zookeeper 下提供了一些常见客户端命令
创建节点:create /aa “value”
查看节点:ls /
查看数据:get /aa
修改数据:set /add “vakue2”
删除节点:rmr /aa
监听数据:get /aa watch
安装HBASE
HBase是一个基于HDFS的NoSQL数据库,可以提供数据的实时随机读写,其中包括的概念有:HMaster、HRegionServer、库名、表名、行键、列族等,其中HBase集群中的各个节点信息是维护在zookeeper中的。
下载安装
下载地址:http://apache.claz.org/hbase/1.2.6.1/
tar -zxvf
HBase中包括两个角色:HMaster、HRegionServer。HMaster负责管理HRegionServer,数据读写交给HRegionServer。其中,HRegionServer应该和HDFS中的DataNode安装在一起。
配置文件
主要修改三个配置文件:hbase-env.sh、hbase-site.xml、regionservers
cd hbase-1.2.6.1/conf
修改hbase-env.sh
export JAVA_HOME=/home/hadoop/jdk1.8
//hbase自己有一套zookeeper管理机制,这里不使用自带的,而是使用我们配置的
export HBASE_MANAGES_ZK=false
修改hbase-site.xml
<configuration>
<!-- 指定hbase在HDFS上存储的路径 -->
<property>
<name>hbase.rootdir</name>
<value>hdfs://master:9000/hbase</value>
</property>
<!-- 指定hbase是分布式的 -->
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<!-- 指定zk的地址,多个用“,”分割 -->
<property>
<name>hbase.zookeeper.quorum</name>
<value>master:2181,slave1:2181,slave2:2181</value>
</property>
</configuration>
修改regionservers,这里就是配置HRegionServer服务器的
slave1
slave2
然后将安装包拷贝到slave1 和 slave2
scr -r hbase-1.2.6.1 hadoop@slave1:/home/hadoop
scr -r hbase-1.2.6.1 hadoop@slave2:/home/hadoop
启动
启动hbase的时候有个要求,需要各个服务器之间时间差不超过30s,所以在启动之前需要先设置同步一下服务器时间,可以选择时间服务器,这里就直接用命令了
date -s "2018-07-08 16:39:03"
//写入bios,防止重启系统时间又变了
hwclock -w
启动hdfs,不启动yarn也没关系,在master服务器启动
cd hadoop-2.7.6
sbin/start-dfs.sh
启动zookeeper,进入三台服务器启动
cd zookeeper-3.4.12
bin/zkServer.sh start
启动hbase
bin/start-hbase.sh
启动之后,三台服务器上的进程分别如下,可以看到hbase已经启动起来了
启动成功之后,也可以在浏览器上观察效果
http://master:16010
前面已经说过,hbase相关的节点信息和zookeeper已经关联了,所以可以在zookeeper上查看hbase相关信息
cd zookeeper-3.4.12
bin/zkCli.sh
Hbase的文件存储是基于HDFS的,所以也可以在hdfs上看到hbase相关的目录
打开浏览器:http://master:50070/explorer.htm
命令行
Hbase提供了一些交互命令,但是这种情况我们用的不多一般是在程序中通过API来对hbase交互。
进入hbase命令行客户端
cd hbase-1.2.6.1
bin/hbase shell
常用命令如下:
常见用法
创建表
create 表名, 列族名, 列族名 ……
create 't_user_info','base_info','extra_info'
插入数据
put 't_user_info','001','base_info:username','zhangsan'
put 't_user_info','001','base_info:age','18'
查询数据
scan 't_user_info'
get 't_user_info','001'
删除kv数据
delete 't_user_info','001','base_info:sex'
deleteall 't_user_info','001'
删除表
先禁用,然后删除
disable 't_user_info'
drop 't_user_info'
API
创建一个连接
Connection conn = ConnectionFactory.createConnection(conf);
拿到一个DDL容器
Admin admin = conn.getAdmin();
用表管理器的API去操作表
admin.createTable(HTableDescriptor descriptor);
创建一个连接
Connection conn = ConnectionFactory.createConnection(conf);
安装Flume
Flume用于数据采集。在实际开发中,有各种各样的数据来源,比如:kafka、mysql、hbase等等,而我们的业务系统,往往需要根据不用的数据来源开发不同的程序。Flume就相当一层壳,并且里面提供了一些常用的实现类,有个核心概念就Agent,可以启动Agent程序进行数据采集,大大减少了我们的开发时间。
不过看网上说,Flume在严格场景是不推荐使用的,会有问题。所以简单了解一下吧。
下载安装
下载地址
http://mirror.bit.edu.cn/apache/flume/1.8.0/apache-flume-1.8.0-bin.tar.gz http://mirrors.hust.edu.cn/apache/flume/1.8.0/apache-flume-1.8.0-bin.tar.gz http://mirrors.shu.edu.cn/apache/flume/1.8.0/apache-flume-1.8.0-bin.tar.gz http://mirrors.tuna.tsinghua.edu.cn/apache/flume/1.8.0/apache-flume-1.8.0-bin.tar.gz
解压并拷贝到其它两台机器
tar -zxvf apache-flume-1.8.0-bin.tar.gz
scp -r flume-1.8.0 hadoop@slave1:/home/hadoop
scp -r flume-1.8.0 hadoop@slave2:/home/hadoop
配置文件
使用Flume主要就是配置了,需要编写的配置内容比较多。 这里就不过多介绍了,有兴趣的网上了解一下。
问题总结
DataNode无法启动
多次执行hadoop namenode -format命令,slave 上的执行这个命令之前,我已经清空了三台服务器下的一些目录,并且停掉了所有进程
cd /home/hadoop/hadoop
rm -rf temp/*
rm -rf hdfs/name/* hdfs/data/*
cd hadoop-2.7.6
rm -rf logs/*
sbin/stop-all.sh
然后在master上执行以下命令
sbin/ hadoop-daemon.sh start namenode
sbin/ hadoop-daemon.sh start datanode
执行该命令后,发现在 master节点上找到了 NameNode 和 DataNode 进行,但是在其它两台服务器上未找到 DataNode 进程。
最后的解决方案:
分别在slave1 和 slave2 上执行 以下命令
sbin/ hadoop-daemon.sh start datanode
这时候可以在 slave1 和 slave2 上找到 DataNode进程。
同时,在浏览器上可以发现3个DataNode
http://192.168.88.21:50070/dfshealth.html#tab-datanode
可能应该在三台服务器上把 hdfs目录下的所有文件和文件夹都清空,或者把整个hdfs目录删除。
同理,对于slave1 和slave2 上的没有NodeManager进程情况,就手动在slave1和slave2上启动
yarn-daemon.sh start nodemanager
http://192.168.88.21:8088/cluster/nodes
脚本启动权限问题
执行 sbin/start-dfs.fs 命令,通过ssh的方式启动slave1和slave2节点,提示没有/tmp目录的权限,但是很好奇都是hadoop用户,启动本地的NameNode却没有权限问题。单丝,虽然提示权限问题,两个DataNode却都已经启动了。
为了去除这个警告,尝试是将 /tmp 目录的权限赋给hadoop用户,分别在三台机器上执行以下命令
chown -R hadoop /tmp
再次重启hadoop
sbin/stat-dfs.sh
sbin/stat-yarn.sh
发现警告已经没有了,同时两台DataNode已经启动成功。
这时候,三台机器下分别启动的进程有
**master**:NameNode、SecondaryNameNode、ResourceManager
**slave1**:DataNode、NodeManager、
**slave2**:DataNode、NodeManager、
可以这样理解:NameNode用于管理DataNode,而ResourceManager用于管理NodeManager。
其实这个问题还有另外一种解决方案,就是修改 etc/hadoop/hadoop.env配置文件,里面有那么个选项可以修改。