一、Hadoop伪分布式部署及eclipse开发环境搭建
1.搭建虚拟机环境: 搭建在win7上的linux虚拟机,套件版本为:CentOS release 6.2 (Final).
2.下载hadoop,我下载的版本是hadoop 1.1.2
3.下载hadoop-eclipse-plugin-1.1.2.jar 或者 在${HADOOPHOME}/contrib/目录下找到 hadoop-eclipse-plugin-1.1.2.jar放到${ECLIPSEHOME}/plugin目录下。
4.虚拟机安装JDK,我用的版本是:java version "1.6.0_45"
5.配置SSH 并设置免登陆:
ssh配置步骤为: (1)检查linux是否安装了SSH,命令为:yum -qa | grep ssh;如果没有安装则执行命令 yum install ssh。
(2)检查ssh服务是否开启,命令为:service sshd status,若已经开启则显示为:
[steven@localhost contrib]$ service sshd status/etc/init.d/sshd: line 33: /etc/sysconfig/sshd: Permission deniedopenssh-daemon (pid 1946) is running...
若没有开启,则开启ssh服务,命令为:service sshd start.
(3)检查ssh是否是自动启动状态,命令为:chk --list sshd:
[steven@localhost contrib]$ chkconfig --list sshdsshd 0:off 1:off 2:on 3:on 4:on 5:on 6:off
ps: 等级0表示:表示关机
等级1表示:单用户模式
等级2表示:无网络连接的多用户命令行模式
等级3表示:有网络连接的多用户命令行模式
等级4表示:不可用
等级5表示:带图形界面的多用户模式
等级6表示:重新启动
以上结果显示是开机自动启动状态,设置开机启动的命令为:chkconfig sshd start
(4)查看当前用户目录下是否有 .ssh目录,如果没有则创建一个。
(5)切换到 root账户,命令为 su - root,在root用户目录下执行命令:ssh-keygen -t rsa。有停顿一路回车直接过。通过以上命令将在/root/.ssh/ 目录下生成idrsa私钥和idrsa.pub公钥,然后进入root/.ssh/目录。执行如下命令:cat idrsa.pub > authorizedkeys。
(6)以上步骤配置完毕后,就可以以免登的方式登录ssh了。测试命令 ssh 127.0.0.1
6.配置hadoop: (1) 将hadoop1.1.2加压到 /usr/local/目录下(这个是规范了,放在其他地也ok),配置hadoop的环境变量,在/etc/profile文件中添加环境变量:
export HADOOP_HOME=/usr/hadoop/hadoop-1.1.2export PATH=$HADOOP_HOME/bin:$PATH
(2) 编辑 ${HADOOP_HOME}/conf/hadoop-env.sh,在其中添加java的环境变量:
export JAVA_HOME=/usr/java
(3) 编辑 ${HADOOPHOME}/conf/core-site.xml,这是hdfs namenode的地址:
fs.default.name hdfs://127.0.0.1:9000/ (4) 编辑 ${HADOOPHOME}/conf/hdfs-site.xml,在其中添加:
dfs.name.dir /home/steven/hadoopdir/datalog1 dfs.data.dir /home/steven/hadoopdir/data1 dfs.replication 1 hadoop.tmp.dir/home/steven/hadooptemp/tmp ps:这里设置的namenode数据存放的地址和datanode数据存放的地址,以及结点的复制份数,和临时目录的地址。
(5)编辑 ${HADOOPHOME}/conf/mapred-site.xml,在其中添加:
<configuration> <property> <name>mapred.job.tracker</name> <value>127.0.0.1:9001</value> </property></configuration>
ps: 这里配置的jobtracker的地址。
7.hadoop的启动: (1) 首先格式化namenode,命令为:hadoop namenode -format。
(2) 执行hadoop启动脚本,命令为:./${HADOOP_HOME}/bin/start-all.sh
正常启动后切换到 root用户,通过jps可以查看到以下5个进程:
28442 SecondaryNameNode28656 TaskTracker28533 JobTracker28312 DataNode28196 NameNode
8.顺利执行以上步骤,则hadoop伪分布式(单机)环境已经搭建完了,可以执行hadoop命令验证下,命令为:
[root@localhost ~]# hadoop fs -ls /home/stevenFound 1 itemsdrwxrwxrwx - root supergroup 0 2014-03-05 04:37 /home/steven/hadoop_temp
9.在本地eclipse开发并调试MR程序:
(1) 打开已经安装插件的eclipse,window-> Preference,配置hadoop的Home目录,如下图:
(2) 打开MapReduce Location视图,window->show view,并配置该Location视图:
配置Location信息:
ps:第一个端口填写 在上文中 mapred-site.xml中配置的端口号,即为JobTracker的ip和端口。第二地址填写namenode的地址及上文中配置在core-site.xml的中的地址。(其实主要看的配置的key,value,其实三个site.xml全配置在一个文件中也是ok的)
(3)MR Location配置完毕如下图:
ps:用 hadoop -copyFromLocal 自己编辑一个文件上传到hdfs中。我上传的文件内容是:
ps:要分析的数据首先要先传递到hdfs环境中。
(4)在eclipse运行Hadoop自带的 WordCount.java程序,并显示运行结果:
在eclipse中新建MapReduce Driver工程,将Hadoop自带的WordCount.java拷贝到工程中。然后右键,run as -> run configurations,在Program VM中添加MR任务的输入输出路径:
ps:这里填写的地址的端口都是9000端口,即namenode的ip和端口。(开始我填写了jobtracker 的ip和端口,报错了)
(5) 然后运行MR程序:
控制台打印了MR任务运行的信息。然后到hdfs上查看输出目录输出的内容如下:
ps:可以看到生成了一个区块。查看区块的内容为:
ps:至此就搭建了一个本地的Hadoop MR程序的本地开发环境 和 hadoop的伪分布式环境,之前写MR都是直接丢到宙斯上去验证正确性,如此在本地虚拟机搭建一个开发环境,开发效率会高许多。
二、Hadoop框架
1.hadoop和MapReduce的关系可以概括的理解为,MapReduce是一种适用于云计算的运算模式,而Hadoop是基于MapReduce模式的一个框架实现。
MapReduce运算模式如下图:
MR模式可以简述为:MR模式将问题空间分解,即将要处理的大数据块切割成若干个小数据块,每个数据块分配一个Map任务,Map任务处理逻辑是按行读入每个数据块的数据,然后以设计好的K/V形式输出。每个Map任务输出产生的数据会交给Reduce任务来处理,数据按一定的原则分配给Reduce任务(比如按key取Hash值来分配任务),reduce将具有相同中间形式K的数据聚集在一起进行计算处理,最终每个Reduce产生一个输出结果。
Hadoop基于MR计算模式的实现如下图(引入一张比较专业的图):
简述:这张图展示了MR执行的整个过程,按照时间维度可以分为如下几个过程:输入分片(input split)、map阶段、combiner阶段、shuffle阶段、reduce阶段。
(1) 输入分片(input split):
Map任务在执行前会计算数据数据的分片,计算分片的原则跟HDFS文件系统设置的block(块)的大小有密切关系,假设HDFS一个块的大小是64M,那么小于64M的文件将作为一个分片,大于64M小于128M的文件将作为两个分片,大于128M小于192M的文件将作为3个分片,以此类推。每个分片对应一个map任务,即5个分片会分别对应5个map任务。输入数据分片不是真的将数据切割成N个数据块,而是由程序维护一个数据位置和分片长度的数组来表示分片。将数据分片后由系统并行执行运算,以提升运算效率。
(2) map阶段:
Map阶段则是依据就近原则,尽量读取本地节点的数据进行计算,Map按行读入数据,并且以K/V的形式输出数据,保存在机器Buffer(缓存)中。
(3) combiner阶段:
Combiner阶段在整个MR计算过程中不是必选的一个环节,Combiner操作是MR计算的一个优化过程,MR任务的瓶颈其实是在网络带宽,为了减少数据在各个节点的复制操作,Combiner会对Map输出的临时文件在本地执行一次Reduce操作,将相同数据key的数据规约到一起,从而减少数据IO。对数据进行Combiner的一个原则就是保证Reduce输入的数据不会出错。例如要计算一个数列的最大值,最小值,可以使用Combiner,如果要计算数列的平均值,使用Combiner就会出错。
(4) shuffle阶段:
将map的输出作为reduce的输入的过程就是shuffle的过程,Shuffle阶段是MR任务要做优化的重点。shuffle阶段的原理:Shuffle一开始就是map阶段做输出操作,一般mapreduce计算的都是海量数据,map输出时候不可能把所有文件都放到内存操作,因此map写入磁盘的过程十分的复杂,更何况map输出时候要对结果进行排序,内存开销是很大的,map在做输出时候会在内存里开启一个环形内存缓冲区,这个缓冲区专门用来输出的,默认大小是100mb,并且在配置文件里为这个缓冲区设定了一个阀值,默认是0.80(这个大小和阀值都是可以在配置文件里进行配置的),同时map还会为输出操作启动一个守护线程,如果缓冲区的内存达到了阀值的80%时候,这个守护线程就会把内容写到磁盘上,这个过程叫spill,另外的20%内存可以继续写入要写进磁盘的数据,写入磁盘和写入内存操作是互不干扰的,如果缓存区被撑满了,那么map就会阻塞写入内存的操作,让写入磁盘操作完成后再继续执行写入内存操作,前面讲到写入磁盘前会有个排序操作,这个是在写入磁盘操作时候进行,不是在写入内存时候进行的,如果定义了combiner函数,那么排序前还会执行combiner操作。每次spill操作也就是写入磁盘操作时候就会写一个溢出文件,也就是说在做map输出有几次spill就会产生多少个溢出文件,等map输出全部做完后,map会合并这些输出文件。这个过程里还会有一个Partitioner操作,Partitioner操作和map阶段的输入分片(Input split)很像,一个Partitioner对应一个reduce作业,如果我们mapreduce操作只有一个reduce操作,那么Partitioner就只有一个,如果我们有多个reduce操作,那么Partitioner对应的就会有多个,Partitioner因此就是reduce的输入分片,这个程序员可以编程控制,主要是根据实际key和value的值,根据实际业务类型或者为了更好的reduce负载均衡要求进行,这是提高reduce效率的一个关键所在。到了reduce阶段就是合并map输出文件了,Partitioner会找到对应的map输出文件,然后进行复制操作,复制操作时reduce会开启几个复制线程,这些线程默认个数是5个,程序员也可以在配置文件更改复制线程的个数,这个复制过程和map写入磁盘过程类似,也有阀值和内存大小,阀值一样可以在配置文件里配置,而内存大小是直接使用reduce的tasktracker的内存大小,复制时候reduce还会进行排序操作和合并文件操作,这些操作完了就会进行reduce计算了。
(5) reduce阶段:
Reduce阶段则是读取Partitioner的数据,将数据按照K/V的形式进行规约。有几个Reduce任务就会产生几个输出文件。
2.JobTracker和TaskTracker:
JobTracker和TaskTracker的关系如上图所示:客户端程序提交一个Job到JobTracker,jobTracker会将任务封装成MapTask和ReduceTask,然后交给多个多个TaskTracker进行运算执行,在TaskTracker执行的过程会实时的和JobTracker保持通信状态,以回报任务的执行状体,而JobClient则实时的监控JobTracker的执行状态以获取Job的执行状态。JobTracker和TaskTracker的关系是Master和Slave的关系。
三、Hadoop的生态系统
1.Hadoop的生态系统结构:
简述:Hadoop的生态系统如上图所示,分解简述一下:
(1)ETL Tools、BIReporting、RDBMS 等是生态系统的数据源。hadoop生态系统要分析获取的数据从这些源头获取。
(2)Pig(Data Flow):pig是hadoop项目的一个拓展项目, 用以简化hadoop编程(简化的程度超乎想象啊),并且提供一个更高层次抽象的数据处理能力,同时能够保持hadoop的简单和可靠性。
例如:
将c分割为d和e,其中d的第一列数据值为0,e的第一列的数据为1($0表示数据集的第一列):grunt> split c into d if $0 == 0, e if $0 == 1;
可见Pig是一个类似于hive基于MR和HDFS的更高层次抽象的数据处理语言。pig是对MapReduce算法实现的一套shell脚本。
(3)Hive(SQL):Hive是基于Hadoop的类似于Sql的数据处理工具。 (4)sqoop:sqoop是Apache顶级项目,主要用来在Hadoop和关系型数据库中传递数据。通过sqoop,我们可以方便的将数据从关系数据库导入到HDFS,或者将数据从HDFS导出到关系型数据库。
sqoop架构:
sqoop主要通过JDBC和关系数据库进行交互。数据的传输通过map-reduce任务来实现,理论上支持JDBC的dataBase都可以使用sqoop和hdfs进行数据交互。
ps:sqoop和我们公司的datax是同一类产品,只不过datax更贴近于淘宝。
(5)MapReduce: MapReduce是hadoop生态系统中并行计算引擎。上面已经详细说了,这里略过。
(6)Hbase: HBase是一种构建在HDFS之上的分布式、面向列的存储系统。
HBase的架构图:
具体HBase的详细资料往这看:http://blog.csdn.net/lantian0802/article/details/20702991
(7)HDFS(Hadoop Distributed FileSystem):
简述:HDFS的全称是 Hadoop 分布式文件系统,主要解决当数据集远远超出单机存储时的集群分布式文件系统。其适用于一次写入,多次读取的场景。HDFS在具体实现上分为 NameNode和DataNode,nameNode主要存储数据的元数据信息,例如:负责管理文件目录、文件和block的对应关系以及block和datanode的对应关系。而DataNode 则是实际存储数据的单位。为了容错,hadoop默认一份数据会冗余3份,分布在不同的datanode上。ps:namenode是整个系统的单点,为了防止当发生单点故障时,丢失元数据信息,通常还会启动一个 secondary namenode来定期的做数据备份和日志数据合并。
(8)ZooKeeper: zookeeper是针对大型分布式系统的高可用的协调系统(Hadoop翻译过来是大象,zooKeeper翻译过来是动物管理员,名字还是比较形象的)。例如:Master结点的选举,Jobtracker及 namenode的单点故障,部分操作失败后的容错协调都是依托Zookeeper来实现的。Zookeeper的核心是一个精简的文件系统,它提供一些简单的的操作和一些额外的操作,例如,排序和通知。
(9)Avro(serialization):
Avro是一个贯穿在整个Hadoop体系中的数据序列化系统,例如它是客户端结点和服务结点的通信数据的标准化序列化和反序列化协议,多个语言程序模块读写数据的标准化协议。具体可参考这篇blog:http://www.alidata.org/archives/1307
ps:淘宝云梯的整体部署结构图:
四、Hadoop 涉及的一些技术细节
通过distcp实现并行复制:
Hadoop有一个有用的distcp分布式复制程序,该程序可以从Hadoop文件系统中复制大量的数据,也可以将大量的数据复制到Hadoop中。例如:如果两个集群运行相同版本的Hadoop,distcp就非常适合在两个Hdfs集群中传输数据的场景。命令如下:${HADOOP_HOME} distcp hdfs://namenode1/foo hdfs://namenode2/bar
将第一个集群的 /foo目录下的数据,通过MR任务并行的拷贝到第二个集群的/bar目录下。
但在运行不同的hdfs版本的集群系统之间拷贝数据采用上述命令就行不通了,例如从现有的云梯环境拷贝数据到Hbase集群环境(使用不同的hdfs版本),因为两个版本的PRC系统是不兼容的。但是仍然可以采用hftp协议实现 目标集群向 源集群拷贝数据的方式,进而实现HDFS RPC版本的兼容。命令如下:
${HADOOP_HOME}/hadoop distcp hftp://namenode1:50070/foo hdfs://namenode2/bar
之前一个bulkload导入数据的实现,就采用了这种数据拷贝方式,实现了跨版本的集群拷贝。
2.UDF和UDAF:
UDF(user-defined function,UDF):用户自定义函数,例如我们写hive通常使用的substr,concat函数属于UDF函数,主要对单行数据字段的做一些转换。
UDAF(User- Defined Aggregation Funcation):用户自定义聚集函数,例如当某些聚集函数,HQL没有实现时,可以自定义聚集函数,UDAF比UDF要难写的多。(sum,avg,max这些都是hql自带的聚集函数).