Hadoop
【亲自测试没问题 于是分享给初学者】
1、Hadoop简介
1、hadoop的诞生
Nutch和Lucene之父Doug Cutting在2006年完成Hadoop项目。
Hadoop并不是一个单词,它来源于DougCutting小儿子对所玩的小象玩具牙牙学语的称呼。就像是google也是由小孩子命名一样。
后又经过5年的开发,hadoop在所有云计算系统是稳居第一。
Hadoop目前使用最广泛的版本为hadoop-0.20版本。目前最新版本为hadoop-1.03。
Hadoop运行在Linux系统中。在windows上安装可使用cgywin模拟linux环境。
2、hadoop的组成
hadoop Common – 是hadoop的核心,包括文件系统、远程调用RPC的序列化函数。
HDFS : 提供高吞吐量的可靠分布式文件系统是 GFS的开源实现。
Hadoop的文件系统。必须通过hadoop fs 命令来读取。支持分布式。
MapReduce : 大型分布式数据处理模型,是Google MapReduce的开源实现。
合并/计算模型。
其他相关组成:
• Hbase:结构化分部式数据库。BigTable的开源实现。
• Hive:提供摘要和查询功能的数据仓库。
• Cassandra:由Facebook开发分布式数据仓库。目前已经捐献给apache。且apache已经将Cassandra应用到了各种云计算系统中。
3、hadoop的体系结构
NameNode - 主节点主服务器
SecondaryNameNode– 是辅助nameNode
DataNode -数据保存用的
TackTracker – 接收任务
JobTracker - 分数据 -100M Datanode1,DataNode2,DataNode3
l NameNode:这是hadoop的守护进程(注意是进程JVM)。负责记录文件是如何分割成数据块,以及这些数据块分别存储到哪些数据节点上。对内存进行集中管理。NameNode在整个hadoop中只有一个。一旦NameNode服务器宕机,整个系统将无法运行。
l DataNode:集群中的每个从服务器都运行一个DataNode后台程序。这个后台程序负责将HDFS数据块写到本地的文件系统。
l Secondary NomeNode:用来监控HDFS状态的辅助后台程序。如保存NameNode的快照。
l JobTracker:用户连接应用程序和hadoop。每一个hadoop集群中只一个 JobTracker,一般它运行在Master节点上。
l TaskTracker:负责与DataNode进行结合。
4、Hadoop的市场
l facebook
l 淘宝
l 360完全
l 京东
l yahoo
l google
l 暴风
2、Hadoop的安装
Core-site.xml:
官方只提供linux的安装版本:
目前市场上出现了一种window上的可以安装的版本。其实是将Linux与hadoop整合的产物。目的是简化hadoop的安装。此安装程序使用的是hadoop-0.20版本+cgywin:
1、hadoop的单机安装-hadoop4win的安装方法
Hadoop的使用包括
n 安装
n 格式化NameNode
n 启动所有节点
Hadoop4win的安装方法非常简单,因为它就是一个setup安装程序,只要会点下一步即可。
选择语言:
接收:
选择组件:
选择安装位置:
等待安装:
查看hadoop的安装细节:
安装细节:
安装细节:格式化namenode:
安装细节-测试启动所有节点:
注意下面的停止顺序:
Hadoop安装完成以后的目录:
hadoop4win是Linux+jdk+hadoop的安装目录。
Var是namenode格式化以后生成的目录 。即hdfs的目录。
进入hadoop4win:
|
查看上面文件的配置信息,你对了解hadoop有帮助。
2、启动hadoop
1、直接使用hadoop的start-haoop
2、使用jsp检查java进程
如果发现有5个java进程,则说明启动成功:
或使用ps命令:
3、单个启动与停止hadoop
启动和停止hadoop必须要遵循节点的顺序。
启动时按以下顺序启动:(停止时按相反的顺序停止)
Namenode
Datanode
Secondarynamenode
Jobtracker
Tasktracker
使用hadoop-daemon.sh start 启动各节点:
检查启动是否成功:
停止:
使用hadoop-daemon.sh stop namenode停止每个节点即可
3、测试访问
Hadoop启动以后,访问50030端口可以访问jobtracker。
访问50070端口可以访问hdfs文件系统。
http://localhost:50030 - Jobtracker
http://localhost:50070 - hdfs
以下是50070
3、hdfs概念与命令
Hdfs是hadoop Distributed file system的缩写,是hadoop的分布式文件系统。
Hdfs由hadoop来管理,它不同于普通的文件系统,不能直观的查找文件,必须要通过hadoop命令操作hdfs。
HDFS是一个主从结构的体系,一个HDFS集群是由一个名字节点,它是一个管理文件的命名空间和调节客户端访问文件的主服务器,当然还有的数据节点,一个节点一个,它来管理存储。HDFS暴露文件命名空间和允许用户数据存储成文件。
内部机制是将一个文件分割成一个或多个的块,这些块存储在一组数据节点中。名字节点操作文件命名空间的文件或目录操作,如打开,关闭,重命名,等等。它同时确定块与数据节点的映射。数据节点来负责来自文件系统客户的读写请求。
数据节点同时还要执行块的创建,删除,和来自名字节点的块复制指示。
名字节点和数据节点都是软件运行在普通的机器之上,机器典型的都是linux,HDFS是用java来写的,任何支持java的机器都可以运行名字节点或数据节点,利用java语言的超轻便型,很容易将HDFS部署到大范围的机器上。典型的部署时将有一个专门的机器来运行名字节点软件,机群中的其他机器运行一个数据节点实例。体系结构排斥在一个机器上运行多个数据节点的实例,但是实际的部署不会有这种情况。
集群中只有一个名字节点极大地简单化了系统的体系。名字节点是仲裁者和所有HDFS的元数据的仓库。系统设计成用户的实际数据不经过名字节点。
1、hadoop下的文件操作命令
1 :列出hdfs文件
~# hadoop dfs –ls /
或
~# hadoop fs –ls /
2:将文件上传到hdfs
以下命令,将本地目录下的a.txt上传到hdfs下的wj目录下,并重命名为b.txt
Hadoop fs –put a.txt /wj/b.txt
也可以使用copyFromLocal命令将本目录下的文件上传到hdfs文件系统中:
3:将hdfs中的文件复制到本地系统中
通过get命令,即可以操作文件也可以操作文件夹:
操作一个文件,将hdfs上的文件/wj/a.txt保存到本地,并取名为b.txt
以下下载整个文件到当前目录下来,注意最后的一个点
4:删除hdsf下的某个文档
5:其他更多操作,可以通过查帮助获取
2、MapReduce 范例操作-测试字符统计
先向服务器上传一文件:
执行统计:
root@linux:/home/wangjian#hadoop fs -copyFromLocal a.txt /wj/a.txt
root@linux:/home/wangjian#cd /opt/hadoop-0.20.2/
root@linux:/opt/hadoop-0.20.2#hadoop jar hadoop-0.20.2-examples.jar wordcount /wj/a.txt /wj/result2
4、查看结果:
默认情况下结果文件名为:/wj/result2/part-0000
root@linux:/opt/hadoop-0.20.2#hadoop fs -cat /wj/result2/part*
4、Java操作hdfs示例
1、配置Eclipse的插件
(非分布式,支持本地)
在eclipse3.6中安装map/redurce插件:
选择map/red视图:
选择添加新地址:
输入以下信息:
配置成功后显示在HDFSLocation显示以下信息:
左图显示的都是服务器的hdsf文件系统。可以方便的进行上传和下载。
2、Java代码
书写代码之前,必须要建立一个新的map/red项目:
1、上传本地文件到HDFS
创建一个Java源代码类:
输入以下代码:(图)
源代码如下:
packagecn.itcast.one;
importorg.apache.hadoop.conf.Configuration;
importorg.apache.hadoop.fs.FileStatus;
importorg.apache.hadoop.fs.FileSystem;
importorg.apache.hadoop.fs.Path;
/**
* 上传本地文件到hdfs
*/
public class One{
public static void main(String[] args)throws Exception {
Configuration conf =
new Configuration();
FileSystem hdfs = FileSystem.get(conf);
Path src = new Path("c:/a.txt");//本地文件
Path dst = newPath("/wj");//hdfs文件
hdfs.copyFromLocalFile(src, dst);
System.err.println("文件上传成功至:"+conf.get("fs.default.name"));
//列出服务器上目前拥有的文件
FileStatus[] fs =hdfs.listStatus(dst);
for(FileStatus f:fs){
System.err.println(f.getPath());
}
}
}
使用map/red运行map方法:
运行完成以后,应该可以/wj/目录下发现一个新的文本文件:
2、创建HDFS文件
通过FileSystem.create(Pathf)可以在HDFS上创建文件,其中f为文件的完整路径:
注意是文件,而不是文件夹。
以下是源代码:
packagecn.itcast.one;
importorg.apache.hadoop.conf.Configuration;
importorg.apache.hadoop.fs.FSDataOutputStream;
importorg.apache.hadoop.fs.FileSystem;
importorg.apache.hadoop.fs.Path;
public classCreatePath {
public static void main(String[] args)throws Exception {
Configuration conf =
new Configuration();
FileSystem fs = FileSystem.get(conf);
//在HDSF上创建一个文件
FSDataOutputStreamout=fs.create(new Path("/wj/c.txt"));
//写入一行数据,必须使用UTF-8
out.writeUTF("Hell使用UTF-8");
out.close();
}
}
3、重命名HDFS文件
4、删除hdfs文件
通过FileSystem.delete(Path f,Booleanrecursive)可以删除指定的HDSF文件,其中f 为完整的路径,cecursive用来确定是否进行递归删除:
5、查看hdfs最后修改时间
FileSystem.getModificationTime()可以查看HDFS文件的最后修改时间。
6、查看某个HDFS文件是否存在
FileSystem.exists(Pathf)可以查看某个HDFS文件是否存在。
7、查找某个文件在HDFS集群中的位置
FileSystem.getFileBlockLocations(FileStatusfile,long start,long len)要查找指定文件在HDFS集群上的位置:
packagecn.itcast.one;
importorg.apache.hadoop.conf.Configuration;
importorg.apache.hadoop.fs.BlockLocation;
importorg.apache.hadoop.fs.FileStatus;
importorg.apache.hadoop.fs.FileSystem;
importorg.apache.hadoop.fs.Path;
public classFindFile {
public static void main(String[] args)throws Exception {
Configuration conf =
new Configuration();
FileSystem fs =FileSystem.get(conf);
//必须是一个具体的文件
Path path = newPath("/wj/a.txt");
//文件状态
FileStatus fileStatus =fs.getFileStatus(path);
//文件块
BlockLocation[] blockLocations=
fs.getFileBlockLocations(fileStatus,0,fileStatus.getLen());
int blockLen =blockLocations.length;
System.err.println(blockLen);
for(int i=0;i<blockLen;i++){
//主机名
String[] hosts =blockLocations[i].getHosts();
for(String host:hosts){
System.err.println(host);
}
}
}
}
8、获取 HDFS集群上所有节点名称
通过DatanodeInfo.getHostName()可以获取HDFS集群上的所有节点名称:
packagecn.itcast.one;
importorg.apache.hadoop.conf.Configuration;
importorg.apache.hadoop.fs.FileSystem;
importorg.apache.hadoop.hdfs.DistributedFileSystem;
importorg.apache.hadoop.hdfs.protocol.DatanodeInfo;
/**
* 获取所有主机节点
*/
public class GetNodes{
public static void main(String[] args)throws Exception {
Configuration conf =
new Configuration();
FileSystem fs =FileSystem.get(conf);
//强转成分布式文件对象
DistributedFileSystem hdfs =
(DistributedFileSystem) fs;
//获取节点信息-数组
DatanodeInfo[] dis =hdfs.getDataNodeStats();
for(DatanodeInfo info : dis){
String name =info.getHostName();
System.err.println(name);
}
}
}
Configuration
FileSystem
Mapper
Redurcer
3、Map/red的java代码-wordcount
其实WordCount并不难,只是一下子接触到了很多的API,有一些陌生,还有就是很传统的开发相比,map-reduce确实是一种新的编程理 念,为了让各位新手少走弯路,我将WordCount中的很多API都做了注释,其实这些方法搞明白了以后程序就很简单了,无非就是将一句话分词,先用 map处理再用reduce处理,最后再main函数中设置一些信息,然后run(),程序就结束了。好了,不废话,直接上代码:
主要的几个核心类说明:
l Mapper<T,T,T,T>- 用于mapper分组处理数据
它可以设置的泛型包括:
n Text :hadoop的Text对应java.lang.String类型
n IntWritable :对应的为Integer类型。
n LongWritable :对应的为Long类型。
l Reducer类用于对mapper以后结果进行合并处理:
1、以下自己实现的wordcount代码:
以下是完整源代码:
packagecn.itcast.count;
importjava.io.IOException;
importjava.util.StringTokenizer;
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;
importorg.apache.hadoop.mapreduce.lib.input.FileInputFormat;
importorg.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
public class MyWordCount {
//Mapper<KEYIN,VALUEIN, KEYOUT, VALUEOUT>//参数说明
publicstatic class MyMapper extends Mapper<Object,Text,Text, IntWritable>{
privatefinal static IntWritable one = new IntWritable(1);//类似于int类型
privateText word = new Text(); //可以理解成String类型
publicvoid map(Object key, Text value, Context context)
throws IOException ,InterruptedException {
System.err.println(key+","+value);
//默认情况下即根据空格分隔字符串
StringTokenizeritr = new StringTokenizer(value.toString());
while(itr.hasMoreTokens()){
word.set(itr.nextToken());
context.write(word,one);
}
};
}
//Reducer<KEYIN,VALUEIN, KEYOUT, VALUEOUT>
publicstatic class MyReducer
extends Reducer<Text,IntWritable,Text, IntWritable>{
privateIntWritable result = new IntWritable();
protectedvoid reduce(Text key, Iterable<IntWritable> values,
Contextcontext)
throws IOException ,InterruptedException {
System.err.println(key+","+values);
intsum=0;
for(IntWritableval:values){
sum+=val.get();
}
result.set(sum);
context.write(key,result);//这是最后结果
};
}
publicstatic void main(String[] args) throws Exception {
//声明配置信息
Configurationconf = new Configuration();
//声明Job
Jobjob = new Job(conf,"Word Count");
//设置工作类
job.setJarByClass(MyWordCount.class);
//设置mapper类
job.setMapperClass(MyMapper.class);
//可选
job.setCombinerClass(MyReducer.class);
//设置合并计算类
job.setReducerClass(MyReducer.class);
//设置key为String类型
job.setOutputKeyClass(Text.class);
//设置value为int类型
job.setOutputValueClass(IntWritable.class);
//设置或是接收输入输出
FileInputFormat.setInputPaths(job,newPath("/wj/b.txt"));
FileOutputFormat.setOutputPath(job,newPath("/wj/out5"));
//执行
System.exit(job.waitForCompletion(true)?0:1);
}
}
2、用Eclipse运行的结果
3、将文件打成jar包用hadoop jar命令运行的结果
4、在Eclipse中运行时出现的问题解决方案
Cannot run program “chmod”: CreateProcesserror=2
这个是说,不能执行chmod这个命令。
解决方案非常简单。
1:关闭Eclipse。
2:将cgywin\bin加入到windows的path环境变量中。
3:启动eclipse再用hadoop运行即可。
5、在Linux上安装hadoop
在Linux中安装hadoop包括在独立的linux系统中安装hadoop和在linux虚拟机下安装hadoop。我本人使用后面的方式安装。即在虚拟机上先安装linux,然后再将hadoop安装到linux下。
1、安装VirtualBox VM虚拟机
(执行setup.exe安装即可)
2、在Vbox中安装Linux系统
(略,相信大家都应该会)
3、设置linux与windows的共享目录
1、在没有插入网线的情况下选择网络模式为:HostOnly
2、选择共享目录:
3、挂载
Linux系统的/mnt目录是挂载其他共享目录的位置:
执行以下命令:
在linux上创建一个挂载目录
挂载:挂载成功以后显示不同的颜色:
4、安装ssh
Hadoop运行过程需要管理远程hadoop守护进程。
1、inux上安装ssh使用以下命令:在网络情况下执行一命令即可以安装
~# sudo apt-get install ssh
如果是在非网络情况下,则需要.deb或是.gz的安装包:
(关于如果安装deb包,请参考ubuntu.doc)
2、设置ssh无密码登录
~# ssh-keygen
输入上面的命令后一路回车即可。
3、拷贝生成的密码文件,默认生成的密码文件在用户名目录下的.ssh目录下
~# cd ~/.ssh
~# cat id_rsa.pub authorized_keys
4、测试是否可以无密码登录
~# ssh localhost
~# who
一般情况下,第一次登录会给出一个错误提示,退出后再次登录即可。
配置好ssh以后,建议使用xshell远程操作linux这样更加方便。
5、启动以后输入以下命令登录:
5、安装hadoop
1、进入目录,将hadoop-0.20.2.tar.gz拷贝到/opt的根目录下去:
2、进入/opt目录安装hadoop
~tar –zxf hadoop-0.20.2.tag.gz
安装成功后多了一个hadoop-0.20.2目录:
3、设置linux环境变量
配置文件:/etc/profile
使用vim进行编辑:
~# vim /etc/profile
在最后面的部分追加hadoop的bin目录:
可以直接拷贝下面的配置,要根据具体情况做出修改:
exportJAVA_HOME=/usr/local/java/jdk1.7.0_02
exportJRE_HOME=/usr/local/java/jdk1.7.0_02/jre
exportCLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
exportPATH=$JAVA_HOME/bin:$JRE_HOME/bin:$JAVA_HOME:$PATH
exportPATH=/opt/hadoop-0.20.2/bin:$PATH
4、配置完成以后,关闭窗口再将打开一个新的窗口,建议使用xshell进行操作,
输入hadoop:
如果给出以下提示,说明配置成功:
6、配置hadoop
1、修改$hadoop_home/conf/core-site.xml
使用vim打开编辑:
<configuration>
<property>
<name>fs.default.name</name>
<value>hdfs://localhost:9000</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/var/hadoop/hadoop-${user.name}</value>
</property>
</configuration>
编辑完成后,使用:wq保存退出。
2、修改$hadoop_home/conf/hdfs.site.xml
<configuration>
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
</configuration>
3、修改mepred-site.xml配置文件:
mapred.child.tmp可以是其他目录。
<configuration>
<property>
<name>mapred.job.tracker</name>
<value>localhost:9001</value>
</property>
<property>
<name>mapred.child.tmp</name>
<value>/opt/temp</value>
</property>
</configuration>
7、启动hadoop
1、在启动hadoop之前必须要先格式化namenode
输入:
root@linux:/opt/hadoop-0.20.2/bin#hadoop namenode -format
2、使用start-all.sh一次全部启动
在linux环境下,使用start-all.sh可以一次全部启动所有的节点,这一点优于在cygwin环境下。可见hadoop确实适合在linux环境下运行:
执行以下命令:
root@linux:/opt/hadoop-0.20.2/bin#start-all.sh
查看是否都启动成功,使用jps命令:
root@linux:/opt/hadoop-0.20.2/bin#jps
如果5个节点都启动成功,则可以正常访问了。
3、测试字符统计
先向服务器上传一文件:
执行统计:
root@linux:/home/wangjian#hadoop fs -copyFromLocal a.txt /wj/a.txt
root@linux:/home/wangjian#cd /opt/hadoop-0.20.2/
root@linux:/opt/hadoop-0.20.2#hadoop jar hadoop-0.20.2-examples.jar wordcount /wj/a.txt /wj/result2
4、查看结果:
默认情况下结果文件名为:/wj/result2/part-0000
root@linux:/opt/hadoop-0.20.2#hadoop fs -cat /wj/result2/part*
8、停止hadoop
root@linux:/opt/hadoop-0.20.2#stop-all.sh
9、逐个启动节点
启动节点按以下顺序进行:
Hadoop-daemon.sh负责单个启动hadoop的节点:
root@linux:/opt/hadoop-0.20.2# hadoop-daemon.sh start namenode
starting namenode, logging to /opt/hadoop-0.20.2/bin/../logs/hadoop-root-namenode-linux.out
root@linux:/opt/hadoop-0.20.2#hadoop-daemon.sh start datanode
starting datanode, logging to /opt/hadoop-0.20.2/bin/../logs/hadoop-root-datanode-linux.out
root@linux:/opt/hadoop-0.20.2#hadoop-daemon.sh start secondarynamenode
starting secondarynamenode, logging to/opt/hadoop-0.20.2/bin/../logs/hadoop-root-secondarynamenode-linux.out
root@linux:/opt/hadoop-0.20.2#hadoop-daemon.sh start jobtracker
starting jobtracker, logging to/opt/hadoop-0.20.2/bin/../logs/hadoop-root-jobtracker-linux.out
root@linux:/opt/hadoop-0.20.2#hadoop-daemon.sh start tasktracker
starting tasktracker, logging to/opt/hadoop-0.20.2/bin/../logs/hadoop-root-tasktracker-linux.out
启动时参数为start即:
Hadoop-daemon.sh start namenode
关闭时参数为stop:
Hadoop-daemon.sh stop namenode
(安装好以后,在Eclipse中写好代码,将打好的jar文件,放到hadoop的主服务器上,执行。)
6、两个示例
1、单词计数:
~# hadoop jar hadoop-example-0.20.2.jar wordcount /data/word.txt /data/out1
2、对一亿个uuid进行排序
~# hadoop jar contrib/streamming/hadoop-0.20.2-streamming.jar -mapper ‘cat’ –reducer ‘wc -l’
-input /data/bigdata.txt -output /data/out2
杨文华
18024582664