1、简要描述如何安装配置一个apache开源版hadoop,描述即可,列出步骤更好
--解压hadoop包,到指定安装文件夹
--配置linux基本网络环境、jdk环境、防火墙环境
--修改主机名,方便后面UI的访问
--修改hadoop/etc/hadoop/conf下的配置文件,根据部署的模式和需要进行配置
--格式化namenode,对数据缓存的的路径进行格式化
--启动hadoop进程
2、请列出正常工作的hadoop集群中hadoop都需要启动哪些进程,他们的作用分别是什么?
--namenode =>HDFS的守护进程,负责维护整个文件系统,存储着整个文件系统的元数据信息,有image+edit log namenode不会持久化存储这些数据,而是在启动时重建这些数据。
--datanode =>是具体文件系统的工作节点,当我们需要某个数据,namenode告诉我们去哪里找,就直接和那个DataNode对应的服务器的后台进程进行通信,由DataNode进行数据的检索,然后进行具体的读/写操作
--secondarynamenode =>一个冗余的守护进程,相当于一个namenode的元数据的备份机制,定期的更新,和namenode进行通信,将namenode上的image和edits进行合并,可以作为namenode的备份使用
--resourcemanager =>是yarn平台的守护进程,负责所有资源的分配与调度,client的请求由此负责,监控nodemanager
--nodemanager => 是单个节点的资源管理,执行来自resourcemanager的具体任务和命令
3、启动hadoop报如下错误,该如何解决?
--1.error org.apache.hadoop.hdfs.server.namenode.NameNode
--找不到主类,应该是配置文件的hadoop的安装位置配置错误,对hadoop-env.sh文件进行检查修改
--2.org.apache.hadoop.hdfs.server.common.inconsistentFSStateException
--这个是存储目录不存在,或者被删除,对namenode进行格式化,或重新格式化,对tmp.dir进行自己的设置
--3.Directory /tmp/hadoop-root/dfs/name is in an inconsistent
--这个和上面一样的,重新设置core-site.xml中hadoop.tmp.dir的值,对namenode进行格式化,
--4.state storage direction does not exist or is not accessible?
--之前是默认的tmp目录,每次重启都会清除这个数据,所以找不到整个文件系统的信息,重新设置core-site.xml中hadoop.tmp.dir的值,对namenode进行格式化,
4、请列出你所知道的hadoop调度器,并简要说明其工作方法?
--1.先进先出调度器(FIFO)
--Hadoop 中默认的调度器,也是一种批处理调度器。它先按照作业的优先级高低,再按照到达时间的先后选择被执行的作业
--2.容量调度器(Capacity Scheduler)
--支持多个队列,每个队列可配置一定的资源量,每个队列采用FIFO调度策略,为了防止同一个用户的作业独占队列中的资源,该调度器会对同一用户提交的作业所占资源量进行限定。调度时,首先按以下策略选择一个合适队列:计算每个队列中正在运行的任务数与其应该分得的计算资源之间的比值,选择一个该比值最小的队列;然后按以下策略选择该队列中一个作业:按照作业优先级和提交时间顺序选择,同时考虑用户资源量限制和内存限制
--3.公平调度器(Fair Scheduler)
--公平调度是一种赋予作业(job)资源的方法,它的目的是让所有的作业随着时间的推移,都能平均的获取等同的共享资源。所有的 job 具有相同的资源,当单独一个作业在运行时,它将使用整个集群。当有其它作业被提交上来时,系统会将任务(task)空闲资源(container)赋给这些新的作业,以使得每一个作业都大概获取到等量的CPU时间。与Hadoop默认调度器维护一个作业队列不同,这个特性让小作业在合理的时间内完成的同时又不"饿"到消耗较长时间的大作业。公平调度可以和作业优先权搭配使用——优先权像权重一样用作为决定每个作业所能获取的整体计算时间的比例。同计算能力调度器类似,支持多队列多用户,每个队列中的资源量可以配置, 同一队列中的作业公平共享队列中所有资源。
5、当前日志采样格式为如下,请编写MapReduce计算第四列每个元素出现的个数
a,b,c,d
a,s,d,f
d,f,g,c 就如此格式,
代码如下,比wordcount还要简单一点,代码差不多的
package make.hadoop.com.four_column;
import java.io.IOException;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.conf.Configured;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
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 org.apache.hadoop.util.Tool;
import org.apache.hadoop.util.ToolRunner;
public class four_column extends Configured implements Tool {
// 1、自己的map类
// 2、继承mapper类,输入的key,输入的value,输出的key,输出的value
public static class MyMapper extends
Mapper {
private IntWritable MapOutputkey = new IntWritable(1);
private Text MapOutputValue = new Text();
@Override
protected void map(LongWritable key, Text value, Context context)
throws IOException, InterruptedException {
String strs = value.toString();
// 分割数据
String str_four = strs.split(",")[3];
MapOutputValue.set(str_four);
System.out.println(str_four);
context.write(MapOutputValue, MapOutputkey);
}
}
// 2、自己的reduce类,这里的输入就是map方法的输出
public static class MyReduce extends
Reducer {
IntWritable countvalue = new IntWritable(1);
@Override
// map类的map方法的数据输入到reduce类的group方法中,得到,再将这个数据输入到reduce方法中
protected void reduce(Text inputkey, Iterable inputvalue,
Context context) throws IOException, InterruptedException {
int sum = 0;
for (IntWritable i : inputvalue) {
System.out.println(i.get());
sum = sum + i.get();
}
// System.out.println("key: "+inputkey + "...."+sum);
countvalue.set(sum);
context.write(inputkey, countvalue);
}
}
// 3运行类,run方法,在测试的时候使用main函数,调用这个类的run方法来运行
/**
* param args 参数是接受main方得到的参数,在run中使用
*/
public int run(String[] args) throws Exception {
Configuration conf = new Configuration();
Job job = Job.getInstance(this.getConf(), "four_column");
// set mainclass
job.setJarByClass(four_column.class);
// set mapper
job.setMapperClass(MyMapper.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
// set reducer
job.setReducerClass(MyReduce.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
// set path
Path inpath = new Path(args[0]);
FileInputFormat.setInputPaths(job, inpath);
Path outpath = new Path(args[1]);
FileOutputFormat.setOutputPath(job, outpath);
FileSystem fs = FileSystem.get(conf);
// 存在路径就删除
if (fs.exists(outpath)) {
fs.delete(outpath, true);
}
job.setNumReduceTasks(1);
boolean status = job.waitForCompletion(true);
if (!status) {
System.err.println("the job is error!!");
}
return status ? 0 : 1;
}
public static void main(String[] args) throws IOException,
ClassNotFoundException, InterruptedException {
Configuration conf = new Configuration();
int atatus;
try {
atatus = ToolRunner.run(conf, new four_column(), args);
System.exit(atatus);
} catch (Exception e) {
e.printStackTrace();
}
}
}
6、hive有哪些方式保存元数据,各有哪些特点?
--1.内嵌Derby数据库存储
--这个是hive默认自带的内嵌数据库,用来储存元数据,但这个在配置了hiveserver2和metastore服务后,不支持多个用户同时登录,不方便对数据库的安全访问
--2.multi user mode
--在自己本地配一个,mysql的数据库用作,hive的元数据的存储数据库,这个需要要自己本地搭建一个mysql数据库,通过配置文件创建一个,hive自己的元数据库,也是我们学习一般会用的方式,配置一般如下
jasbdaksbdaskbdoajsbdasbu
javax.jdo.option.ConnectionURL
jdbc:mysql://hostname:3306/hive?createDatabaseIfNotExist=true
JDBC connect string for a JDBC metastore
hive.metastore.uris
thrift://hostname:9083
IP address (or fully-qualified domain name) and port of the metastore host
javax.jdo.option.ConnectionDriverName
com.mysql.jdbc.Driver
Driver class name for a JDBC metastore
javax.jdo.option.ConnectionUserName
xxxx
username to use against metastore database
javax.jdo.option.ConnectionPassword
xxxx
password to use against metastore database
--3.remote server mode
--一种在远端配置数据库服务的方式,这个需要配置metastore服务,通过客户端的metastore服务访问服务器上的元数据库达到访问数据的目的
7、 请简述hadoop怎么样实现二级排序?
--在MapReduce中本身就会对我们key进行排序,所以我们要对value进行排序,主要思想为将key和部分value拼接成一个组合key(实现WritableComparable接口或者调用 setSortComparatorClass函数),这样reduce获取的结果便是先按key排序,后按value排序的结果,在这个方法中,用户需 要自己实现Paritioner,继承Partitioner<>,以便只按照key进行数据划分。Hadoop显式的支持二次排序,在Configuration类中有个 setGroupingComparatorClass()方法,可用于设置排序group的key值。
8、用非递归方法实现二分查找
--代码如下,二分查找只适用于有序数列,对其进行查找,效率非常高,不适用于无序数列
public static int binSearch(int srcArray[], int key) {
int mid;
int start = 0;
int end = srcArray.length - 1;
while (start <= end) {
mid = (end - start) / 2 + start;
if (key < srcArray[mid]) {
end = mid - 1;
} else if (key > srcArray[mid]) {
start = mid + 1;
} else {
return mid;
}
}
return -1;
}
递归的二分查找
public static int binSearch_di(int srcArray[], int start, int end, int key) {
int mid = (end - start) / 2 + start;
if (srcArray[mid] == key) {
return mid;
}
if (start >= end) {
return -1;
} else if (key > srcArray[mid]) {
return binSearch_di(srcArray, mid + 1, end, key);
} else if (key < srcArray[mid]) {
return binSearch_di(srcArray, start, mid - 1, key);
}
return -1;
}
9、请简述mapreduce中,combiner,partition作用?
--在MapReduce整个过程中,combiner是可有可无的,需要是自己的情况而定,如果只是单纯的对map输出的key-value进行一个统计,则不需要进行combiner,combiner相当于提前做了一个reduce的工作,减轻了reduce端的压力,
Combiner只应该适用于那种Reduce的输入(key:value与输出(key:value)类型完全一致,且不影响最终结果的场景。比如累加,最大值等,也可以用于过滤数据,在 map端将无效的数据过滤掉。
在这些需求场景下,输出的数据是可以根据key值来作合并的,合并的目的是减少输出的数据量,减少IO的读写,减少网络传输,以提高MR的作业效率。
1.combiner的作用就是在map端对输出先做一次合并,以减少传输到reducer的数据量.
2.combiner最基本是实现本地key的归并,具有类似本地reduce,那么所有的结果都是reduce完成,效率会相对降低。
3.使用combiner,先完成的map会在本地聚合,提升速度.
--partition意思为分开,分区。它分割map每个节点的结果,按照key分别映射给不同的reduce,也是可以自定义的。其实可以理解归类。也可以理解为根据key或value及reduce的数量来决定当前的这对输出数据最终应该交由哪个reduce task处理
partition的作用就是把这些数据归类。每个map任务会针对输出进行分区,及对每一个reduce任务建立一个分区。划分分区由用户定义的partition函数控制,默认使用哈希函数来划分分区。
HashPartitioner是mapreduce的默认partitioner。计算方法是
which reducer=(key.hashCode() & Integer.MAX_VALUE) % numReduceTasks,得到当前的目的reducer。
10、HDFS数据写入实现机制
--写入HDFS过程:
1、根namenode通信请求上传文件,namenode检查目标文件是否已存在,父目录是否存在
2、namenode返回是否可以上传
3、client会先对文件进行切分,比如一个blok块128m,文件有300m就会被切分成3个块,一个128M、一个128M、一个44M请求第一个 block该传输到哪些datanode服务器上
4、namenode返回datanode的服务器
5、client请求一台datanode上传数据(本质上是一个RPC调用,建立pipeline),第一个datanode收到请求会继续调用第二个datanode,然后第二个调用第三个datanode,将整个pipeline建立完成,逐级返回客户端
6、client开始往A上传第一个block(先从磁盘读取数据放到一个本地内存缓存),以packet为单位(一个packet为64kb),当然在写入的时候datanode会进行数据校验,它并不是通过一个packet进行一次校验而是以chunk为单位进行校验(512byte),第一台datanode收到一个packet就会传给第二台,第二台传给第三台;第一台每传一个packet会放入一个应答队列等待应答
7、当一个block传输完成之后,client再次请求namenode上传第二个block的服务器。
--读取文件过程:
使用HDFS提供的客户端开发库Client,向远程的Namenode发起RPC请求;Namenode会视情况返回文件的部分或全部block列表,对于每个block,Namenode都会返回有该block拷贝的DataNode地址;客户端开发库Client会选取离客户端最接近的DataNode来读取block;如果客户端本身就是DataNode,那么将从本地直接获取数据.读取完当前block的数据后,关闭与当前的DataNode连接,并为读取下一个block寻找最佳的DataNode;当读完列表的block后,且文件读取还没有结束,客户端开发库会继续向Namenode获取下一批的block列表。读取完一个block都会进行 checksum 验证,如果读取 datanode 时出现错误,客户端会通知 Namenode,然后再从下一个拥有该 block 拷贝的 datanode 继续读。
11、hadoop节点的动态上线下线的大概操作
--节点上线
1.关闭新增节点的防火墙
2.在 NameNode节点的hosts文件中加入新增数据节点的hostname
3.在每个新增数据节点的hosts文件中加入NameNode的hostname
4.在NameNode节点上增加新增节点的SSH免密码登录的操作
5.在NameNode节点上的dfs.hosts中追加上新增节点的hostname,
6.在其他节点上执行刷新操作:hdfs dfsadmin -refreshNodes
7.在 NameNode 节点上,更改slaves文件,将要上线的数据节点hostname追加
到slaves文件中
8.启动DataNode节点
9.查看NameNode的监控页面看是否有新增加的节点
--节点下线
1.修改/conf/hdfs-site.xml文件
2.确定需要下线的机器,dfs.osts.exclude文件中配置好需要下架的机器,这个是阻
止下架的机器去连接NameNode
3.配置完成之后进行配置的刷新操作./bin/hadoop dfsadmin -refreshNodes,这个
操作的作用是在后台进行block块的移动
4.当执行三的命令完成之后,需要下架的机器就可以关闭了,可以查看现在集
群上连接的节点,正在执行 Decommission,会显示:
Decommission Status : Decommission in progress 执行完毕后,会显示:
Decommission Status : Decommissioned
5.机器下线完毕,将他们从 excludes 文件中移除。
暂时写到这