环境准备:
操作系统:Red Hat5.8 64bit 内核版本2.6.18-308.el5
JDK版本:jdk1.7.0_60
下载jdk-7u60-linux-x64.gz,并解压tar –zvxf jdk-7u60-linux-x64.gz
配置环境变量
export PATH
export JAVA_HOME=/usr/java/jdk1.7.0_60
export PATH=$PATH:$JAVA_HOME/bin
source /etc/profile
测试下JDK是否安装成功: java –version
maven版本:apache-maven-3.1.1
下载地址:http://mirror.bit.edu.cn/apache/maven/maven-3/3.1.1/binaries/apache-maven-3.1.1-bin.zip
解压文件后,同样在/etc/profie里配置环境变量:
export MAVEN_HOME=/usr/maven/apache-maven-3.1.1
export PATH=$PATH:$MAVEN_HOME/bin
修改配置文件:
修改maven目录下的conf/settings.xml文件,在<mirrors></mirros>里添加,原本的不要动:
<mirror>
<id>nexus-osc</id>
<mirrorOf>*</mirrorOf>
<name>Nexusosc</name>
<url>http://maven.oschina.net/content/groups/public/</url>
</mirror>
同样,在<profiles></profiles>内新添加
<profile>
<id>jdk-1.7</id>
<activation>
<jdk>1.7</jdk>
</activation>
<repositories>
<repository>
<id>nexus</id>
<name>local private nexus</name>
<url>http://maven.oschina.net/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>nexus</id>
<name>local private nexus</name>
<url>http://maven.oschina.net/content/groups/public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</profile>
验证配置是否成功: mvn –version
protoc版本:protobuf-2.5.0
下载地址:
https://code.google.com/p/protobuf/downloads/list
对protoc进行编译安装前先要装几个依赖包:gcc,gcc-c++,make
yum install gcc
yum intall gcc-c++
yum install make
安装protoc过程
tar -xvf protobuf-2.5.0.tar.bz2
cd protobuf-2.5.0
./configure --prefix=/opt/protoc/
make && make install
配置环境变量
export PROTOC_HOME=/usr/protoc/protoc
export PATH= $PROTOC_HOME/bin
验证安装是否成功:
ant版本:apache-ant-1.9.4
下载地址:
http://archive.apache.org/dist/ant/source/apache-ant-1.9.4-src.tar.bz2
解压后,配置环境变量
export ANT_HOME=/usr/ant/apache-ant-1.9.4
export PATH= $ANT_HOME/bin
验证安装是否成功:
yum install cmake
yum install openssl-devel
yum install ncurses-devel
源码下载地址:
http://mirrors.hust.edu.cn/apache/hadoop/common/hadoop-2.4.0/
进入hadoop2.4.0源码目录下编译:
mvn package -Pdist,native -DskipTests –Dtar
第一次编译需要联网,等待1个小时左右,看到这样的信息,就代表完成。
[INFO] Reactor Summary:
[INFO]
[INFO] Apache Hadoop Main................................ SUCCESS [3.709s]
[INFO] Apache Hadoop Project POM......................... SUCCESS [2.229s]
[INFO] Apache Hadoop Annotations......................... SUCCESS [5.270s]
[INFO] Apache Hadoop Assemblies.......................... SUCCESS [0.388s]
[INFO] Apache Hadoop Project Dist POM.................... SUCCESS [3.485s]
[INFO] Apache Hadoop Maven Plugins....................... SUCCESS [8.655s]
[INFO] Apache Hadoop Auth................................ SUCCESS [7.782s]
[INFO] Apache Hadoop Auth Examples....................... SUCCESS [5.731s]
[INFO] Apache Hadoop Common.............................. SUCCESS [1:52.476s]
[INFO] Apache Hadoop NFS................................. SUCCESS [9.935s]
[INFO] Apache Hadoop Common Project...................... SUCCESS [0.110s]
[INFO] Apache Hadoop HDFS................................ SUCCESS [1:58.347s]
[INFO] Apache Hadoop HttpFS.............................. SUCCESS [26.915s]
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
[INFO] Apache Hadoop Tools Dist.......................... SUCCESS [2.306s]
[INFO] Apache Hadoop Tools............................... SUCCESS [0.037s]
[INFO] Apache Hadoop Distribution........................ SUCCESS [21.579s]
[INFO] Apache Hadoop Client.............................. SUCCESS [7.299s]
[INFO] Apache Hadoop Mini-Cluster........................ SUCCESS [7.347s]
[INFO]------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 11:53.144s
[INFO] Finished at: Fri Nov 22 16:58:32 CST2013
[INFO] Final Memory: 70M/239M
[INFO]------------------------------------------------------------------------
编译后的路径在:hadoop-2.4.0-src/hadoop-dist/target/hadoop-2.4.0.tar.gz
编译完成!
1)hostname master
2)修改/etc/sysconfig/network中的hostname
3)修改/etc/hosts文件中添加IP和主机名称对应关系
修改后记得重启系统。
所有机器执行/usr/bin/ssh-keygen-t rsa命令,执行完此命令后会在家目录的.ssh目录下生成id_rsa 私钥和id_rsa.pub公钥。
将所有主机的公钥id_rsa.pub汇总到一个名称为authorized_keys的文件中,并分发到各个主机。
测试配置是否成功:
在每台主机都要ssh其他所有主机(包括ssh自己)进行测试。
用root用户解压tar –zxvf hadoop-2.4.0.tar.gz
新增用户:useradd hadoop
新增用户组:groupadd hadoop
将文件夹" hadoop-2.4.0"读写权限分配给hadoop用户:
chown–R hadoop:hadoop hadoop-2.4.0
chmod –R770 hadoop-2.4.0
vim /etc/profile
export HADOOP_HOME=/home/hadoop/hadoop-2.4.0
export PATH= $ HADOOP _HOME/bin
source /etc/profile
需修改hadoop-env.sh
yarn-env.sh
slaves
core-site.xml
hdfs-site.xml
mapred-site.xml
yarn-site.xml
1)vimhadoop-env.sh
export JAVA_HOME=/usr/java/jdk1.7.0_60
export HADOOP_OPTS=-Djava.net.preferIPv4Stack=true
2)vimyarn-env.sh
export JAVA_HOME= /home/hadoop/jdk7
3)vim slaves
添加节点
slave1
slave2
4)vimcore-site.xml
添加
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://master:9000</value>
</property>
<property>
<name>io.file.buffer.size</name>
<value>131072</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/home/hadoop/tmp</value>
<description>Abase for other temporarydirectories.</description>
</property>
<property>
<name>hadoop.proxyuser.hduser.hosts</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.hduser.groups</name>
<value>*</value>
</property>
<property>
<name>fs.trash.interval</name>
<value>360</value>
</property>
<property>
<name>dfs.namenode.checkpoint.period</name>
<value>900</value>
</property>
<property>
<name>ipc.client.connection.maxidletime</name>
<value>30000</value>
</property>
</configuration>
5)vimhdfs-site.xml
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>master:9001</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>/home/hadoop/dfs/name,</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>/home/hadoop/dfs/data</value>
</property>
<property>
<name>dfs.replication</name>
<value>2</value>
</property>
<property>
<name>dfs.webhdfs.enabled</name>
<value>true</value>
</property>
<property>
<name>dfs.datanode.max.xcievers</name>
<value>4096</value>
</property>
<property>
<name>dfs.datanode.data.dir.perm</name>
<value>750</value>
</property>
<property>
<name>dfs.blocksize</name>
<value>134217728</value>
</property>
6)vimmapred-site.xml
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<property>
<name>mapreduce.jobhistory.address</name>
<value>172.16.145.73:10020</value>
</property>
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>172.16.145.73:19888</value>
</property>
7)vimyarn-site.xml
<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>
将在master配置好的hadoop文件传送到其他服务器
scp -r /home/hadoop/hadoop-2.4.0 root@slave1:/home/hadoop/hadoop-2.4.0
scp -r /home/hadoop/hadoop-2.4.0 root@slave2:/home/hadoop/hadoop-2.4.0
配置其他机器用户、用户组及权限
新增用户:useradd hadoop
新增用户组:groupadd hadoop
将文件夹"hadoop"读写权限等分配给hadoop用户:
chown–R hadoop:hadoop hadoop-2.4.0
chmod –R770 hadoop-2.4.0
mkdir/home/hadoop/tmp
mkdir/home/hadoop/dfs
mkdir/home/hadoop/dfs/name
mkdir/home/hadoop/dfs/data
启动前需关闭所有机器的防火墙
chkconfig iptables off
在"master"上使用普通用户hadoop进行进行namenode操作。只需第一次启动时操作,下次启动不需要。
hadoop namenode –format
启动hadoop
start-all.sh
在namenode和datanode使用jps查看启动进程。
1)记录每个文件数据块在各个datanode上的位置和副本信息
2)协调客户端对文件的访问
3)使用事务日志edits记录hdfs元数据的变化。使用映像文件fsimage存储文件系统的命名空间,包括文件映射,文件属性等信息。
1)负责所在物理节点的存储管理
2)一次写入,多次读取
3)文件由数据块组成
4)数据块尽量散步到各个节点
1)定期合并fsimage和edits日志
客户端要访问hdfs中的一个文件,首先从namenode获得组成这个文件的数据块位置列表,根据这个列表知道存储数据块的datanode,访问datanode获取数据,在这个过程中,namenode并不参与数据的实际传输。
1)冗余副本策略。所有文件都有副本数。
2)机架策略。集群服务器可以放在不同的机架上,一个机架一个交换机,最后通过总的交换机进行数据传输,这样可以防止一旦一个机架失效,防止数据找不到。
3)心跳机制。Namenode周期性从datanode接收心跳信号和块的报告,namenode根据块报告验证元数据,没有按时发送心跳的datanode会被标记为宕机,并且namenode不会再向此机器发送I/O请求。如果datanode失效造成副本数量下降,namenode会检测出这些数据块,并在合适的时机进行重新复制。
4)安全模式。Namenode启动时会先经过一个“安全模式”阶段,安全模式阶段不会产生数据写入。在此阶段namenode收集各个datanode的报告,当数据块达到最小副本数以上时,退出安全模式。当检测到副本数不足的数据块时,该数据块会被复制直到达到最小副本数。
5)回收站。开启回收站模式,删除文件时,文件放入/user/root/trash中,回收站里的文件可以快速恢复。可以设置一个时间阈值,当回收站的文件存放时间超过这个阈值时,释放数据块。
6)元数据保护。映像文件fsimage和日志文件edits可以保存多份,在配置文件中填写多个路径,并用逗号隔开,元数据的副本数会降低namenode的处理速度,但增加元数据安全性。
1、列出所有HadoopShell支持的命令
$ hadoop fs -help
2、格式化一个新的分布式文件系统:
$ bin/hadoop namenode-format
3、将集群置于安全模式(dfs.namenode.safemode.threshold-pct选项配置)
$ bin/hadoop dfsadmin-safemode enter
4、退出安全模式
$ bin/hadoop dfsadmin -safemode leave
5、显示Datanode列表及使用情况
$ bin/hadoop dfsadmin -report
6、查看文件目录文件
$ hadoop fs -ls /
7、创建一个名为 /test1 的目录
$ bin/hadoop fs -mkdir /test1
8、查看名为 /hadoop_test.txt 的文件内容
$ bin/hadoop fs -cat /hadoop_test.txt
9、删除文件
$hadoop fs -rm /hadoop_test1.txt
10、上传文件
$hadoop fs -put /home/tmp/upload/hadoop_test1.txt /
11、下载文件
$hadoop fs -get / hadoop_test1.txt /home/tmp/download
12、显示文件大小
$hadoop fs –du /
13、显示文件系统大小
$hadoop fs –df /
14、显示目录数量
$hadoop fs –count /
15、清空回收站
$hadoop fs –expunge
16、设置文件副本数
$hadoop fs –setrep5 /hadoop_test1.txt
代码:
package dealfiles;
importjava.io.IOException;
importjava.io.InputStream;
import java.net.URI;
importorg.apache.hadoop.conf.Configuration;
importorg.apache.hadoop.fs.FileSystem;
importorg.apache.hadoop.fs.Path;
importorg.apache.hadoop.io.IOUtils;
public class hdfs_test {
public static void main(String[] args) throws Exception {
if (args[0].equals("read")) {
readFile(args[1]);
} else if (args[0].equals("upload")) {
uploadFile(args[1]);
} else if (args[0].equals("download")) {
downloadFile(args[1]);
}
else {
System.out.println("请输入正确操作");
}
}
/***
* 加载配置文件
* **/
static Configuration conf = new Configuration();
static String uri = "hdfs://172.16.145.73:9000/";
/***
*
* 读取HDFS某个文件夹的所有文件,并打印
*
* **/
public static void readFile(String string) throws Exception {
String path = "hdfs://172.16.145.73:9000/";
Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(URI.create(uri), conf);
InputStream in = null;
try {
in = fs.open(new Path(path + string));
IOUtils.copyBytes(in, System.out, 4096, false);
} finally {
IOUtils.closeStream(in);
}
}
/**
* 从HDFS上下载文件或文件夹到本地
*
* **/
public static void downloadFile(String string1) throwsException {
FileSystem fs = FileSystem.get(URI.create(uri), conf);
Path p1 = newPath("hdfs://172.16.145.73:9000/" + string1);
Path p2 = new Path("/home/tmp/download/");
fs.copyToLocalFile(p1, p2);
fs.close();// 释放资源
System.out.println("下载文件夹或文件成功.....");
}
/***
* 上传本地文件到 HDFS上
*
* **/
public static void uploadFile(String string1)
throws Exception {
// 加载默认配置
FileSystem fs = FileSystem.get(URI.create(uri), conf);
// 本地文件
Path src = new Path("/home/tmp/upload/" +string1);
// HDFS为止
Path dst = newPath("hdfs://172.16.145.73:9000/tmp");
try {
fs.copyFromLocalFile(src, dst);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("上传成功........");
fs.close();// 释放资源
}
}
地址:http://master:50070/
1)在新节点上安装好hadoop
2)将namenode的有关配置文件复制到该节点
3)修改所有节点的slaves配置文件,增加该节点
4)全部重新设置ssh免密码登录
5)单独启动该节点的hdfs服务和yarn服务
6)运行start-balancer.sh进行数据负载均衡
含有两个模型,map和reduce。Map可以理解为数据准备及数据预处理,reduce接收map传过来的数据进行相应计算。
找出每一年的最高气温。
需求:终端日数据表,统计同一用户同一终端出现的次数。
代码:
Mapper:
package mapreduce;
importjava.io.IOException;
importorg.apache.hadoop.io.IntWritable;
importorg.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
public class MapClassextends Mapper<Object, Text, Text, IntWritable> {
private Text record = new Text();
private static final IntWritable recbytes = newIntWritable(1);
public void map(Object key, Text value, Context context)
throws IOException, InterruptedException {
String line = value.toString();
// 采用 line读取每一行
// key 就是行号,value 就是行内容,
// 按行key-value 存放每行 user_id 和 dm_model 内容
if (line == null || line.equals(""))
return;
String[] words = line.split(",");
if (words == null || words.equals(""))
return;
String user_dm = words[1]+":"+words[6];
record.clear();
record.set(newStringBuffer().append(user_dm).toString());
context.write(record, recbytes);
// 输出日志级别统计结果,通过user_id+dm_model作为结果输出
}
}
Partitioner:
package mapreduce;
importorg.apache.hadoop.io.IntWritable;
importorg.apache.hadoop.io.Text;
importorg.apache.hadoop.mapreduce.Partitioner;
public classPartitionerClass extends Partitioner<Text, IntWritable> {
public int getPartition(Text key, IntWritable value, intnumPartitions) {
//return new Long(key.getDepartureNode()).hashCode() %numPartitions;
if (numPartitions >= 2)// Reduce 个数
if (key.toString().startsWith("18"))//判断user_id,分配到不同的Reduce
return 0;
else
return 1;
else
return 0;
}
}
Reducer:
package mapreduce;
importjava.io.IOException;
importorg.apache.hadoop.io.IntWritable;
importorg.apache.hadoop.io.Text;
importorg.apache.hadoop.mapreduce.Reducer;
public class ReduceClassextends Reducer<Text, IntWritable, Text, IntWritable> {
private IntWritable result = new IntWritable();
public void reduce(Text key, Iterable<IntWritable>values, Context context)
throws IOException, InterruptedException {
int num = 0;
for (IntWritable val : values) { //遍历整个value,进行计数加1操作
num = num + val.get();
}
result.set(num);
context.write(key, result);// 输出最后的汇总结果
}
}
Job:
package mapreduce;
import java.io.File;
importjava.text.SimpleDateFormat;
import java.util.Date;
import org.apache.hadoop.conf.Configuration;
importorg.apache.hadoop.conf.Configured;
importorg.apache.hadoop.fs.Path;
importorg.apache.hadoop.io.IntWritable;
importorg.apache.hadoop.io.Text;
importorg.apache.hadoop.mapred.JobConf;
import org.apache.hadoop.mapreduce.Job;
importorg.apache.hadoop.mapreduce.lib.input.FileInputFormat;
importorg.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
importorg.apache.hadoop.util.Tool;
importorg.apache.hadoop.util.ToolRunner;
public class JobClassextends Configured implements Tool {
public static void main(String[] args) {
try {
int res;
res = ToolRunner.run(new Configuration(), newJobClass(), args);
System.exit(res);
} catch (Exception e) {
e.printStackTrace();
}
}
public int run(String[] args) throws Exception {
if (args == null || args.length < 2) {
System.out.println("需要输入和输出路径");
return 1;
}
String inputpath = args[0];
String outputpath = args[1];
Job job = new Job(new Configuration());//设置配置文件
job.setJarByClass(JobClass.class);//指定job的Class
job.setJobName("JobClass");//设置任务名
job.setOutputKeyClass(Text.class);// 输出的 key 类型
job.setOutputValueClass(IntWritable.class); // 输出的 value 类型
job.setMapperClass(MapClass.class);//指定Mapper的class
job.setCombinerClass(ReduceClass.class);//指定combiner的class
job.setReducerClass(ReduceClass.class);//指定Reducer的class
job.setPartitionerClass(PartitionerClass.class);//指定Partitioner的class
job.setNumReduceTasks(2);//需要有两个 Reduce 来工作
FileInputFormat.setInputPaths(job, newPath(inputpath));// hdfs 中的输入路径
FileOutputFormat.setOutputPath(job, newPath(outputpath));// hdfs 中输出路径
Date startTime = new Date();
System.out.println("Job 开始: " + startTime);
job.waitForCompletion(true);
Date end_time = new Date();
System.out.println("Job 结束: " + end_time);
System.out.println("共用时"
+ (end_time.getTime() -startTime.getTime()) / 1000
+ " seconds.");
return 0;
}
}