2015Hadoop数据处理实战视频教程笔记
hadoop_hdfs_分布式文件系统
Hadoop是Google的集群系统的开源实现
-Google集群系统:GFS(Google File System)、MapReduce、BigTable
-Hadoop主要由HDFS(hadoop distributed File System Hadoop分布式文件系统)、MapReduce和Hbase组成
-Hadoop的初衷是为了解决Nutch海量数据爬取和存储的需要
-Hadoop与2005年秋天作为Lucene的子项目Nutch的一部分正式引入Apache基金会。
-名称起源:Doug Cutting儿子的黄色大象玩具的名字
--------------------------------------------------------------------
两大核心设计
MapReduce HDFS
Map:任务分解 NameNode
Reduce:结果的汇总 DataNode
Client
------------------------------------------------------------------------
|Hadoop---大数据vs传统数据 |
| | 传统数据 | 大数据 |
|数据量 | GB-》TB | TB-》PB |
|速度 | 数据量稳定,增长不快 | 持续实时产生数据,年增长率超过60%|
|多样化 | 主要为结构化数据 | 半结构化,非结构化,多维数据 |
|价值 | 统计和报表 | 数据挖掘和预测性分析 |
------------------------------------------------------------------------
"大数据"指数据集的大小超过了现有典型的数据库软件和工具的处理能力。与此同时,及时捕捉、存储、聚合、管理这些大数据以及对数据的深度分析和新技术和新能力,正在快速增长,就像预测计算芯片增长速度的摩尔定律一样。
-------------------------------------------------------------------------------------------------------------------------------------------------------
并行关系数据库 | MPP or Hadoop
1、多个独立的关系数据库服务器,访问共享的存储资源池 |1、由大量独立的服务器通过网络互连形成集群,每个服务器带存储。
优势: |2、优势:计算与存储融合,支持横向扩展,更好的扩展性
采用多个关系数据库服务器,多个存储,与原有的架构相比,扩展了存储容量和计算能力 |3、劣势:解决数据冲突时需要节点间协作
劣势: |4、适用范围:
计算与存储分离,数据访问存在竞争和带宽瓶颈 | 数据仓库和离线数据分析(MPP,Hadoop/HBase)
支持的关系数据库服务器数量有限 | 大规模在线实时应用(单行事务处理能满足的场景)(HBase)
只能向上扩展,不能横向扩展 |
适合复杂的需要事务处理的应用 |
----------------------------------------------------------------------------------------------------------------------------------------------------
Core:一套分布式文件系统以及支持Map-Reduce的计算框架
Avro:定义了一种用于支持大数据应用的数据格式,并为这种格式提供了不同的编程语言的支持
HDFS:Hadoop分布式文件系统
Map/Reduce:是一种使用简易的软件框架,基于它写出来的应用程序能够运行在由上千个商用机器组成的大型集群上,并以一种可靠容错的方式并行处理上T级别的数据集
ZooKeeper:是高可用的和可靠的分布式协同系统
Pig:建立于Hadoop Core之上为并行计算环境提供了一套数据工作流语言和执行框架
Hive:是为提供简单的数据操作而设计的下一代分布式数据仓库。它提供了简单的类似SQL的语法的HiveQL语言进行数据查询
Hbase:建立于Hadoop Core之上提供一个可扩展的数据库系统
Flume:一个分布式、可靠、和高可用的海量日志聚合的系统,支持在系统中定制各类数据发送方,用于收集数据
Mahout:是一套具有可扩充能力的机器学习类库
Sqoop:是Apache下用于RDBMS和HDFS互相导数据的工具
------------------------------------------------
HDFS介绍
HDFS为了做到可靠性(reliability)创建了多份数据块(data blocks)的复制(replicas),并将它们放置在服务器群的计算节点中(compute nodes),MapReduce就可以在它们所在的节点上处理这些数据了。
------------------------------------------------------------------------
NameNode |DataNode |
存储元数据 |存储文件内容 |
元数据保存在内存中 |文件内容保存在磁盘 |
保存文件,block,datanode |维护了block id到datanode本地文件的映射关系 |
之间的映射关系 | |
------------------------------------------------------------------------
一个名字节点和多个数据节点
数据复制(冗余机制)
--存放的位置(机架感知策略)
故障检测
--数据节点
心跳包(检测是否宕机)
块报告(安全模式下检测)
数据完整性检测(校验和比较)
--名字节点(日志文件、镜像文件)
空间回收机制
HDFS优点:
--高容错性
数据自动保存多个副本
副本丢失后,自动恢复
--适合批处理
移动计算而非数据
数据位置暴露给计算框架
--适合大数据处理
GB、TB、甚至PB级数据
百万规模以上的文件数量
10k+节点
--可构建在廉价机器上
通过多副本提高可靠性
提供了容错和恢复机制
HDFS缺点:
--低延迟数据访问
比如毫秒级
低延迟与高吞吐率
--小文件存取
占用NameNode大量内存
寻到时间超过读取时间
--并发写入、文件随机修改
一个文件只能有一个写者
仅支持append
--------------------------------------------------------------
HDFS架构
HDFS Cient<----->NameNode<----->Seconddary NameNode
|
|
|
DataNode DataNode DataNode DataNode
--------------------------------------------------------------
HDFS数据存储单元(block)
-文件被切分成固定大小的数据块
默认数据块大小为64MB,可配置
若文件大小不到64MB,则单独存成一个block
一个文件存储方式
按大小被切分成若干个block,存储到不同节点上
默认情况下每个block都有三个副本
Block大小和副本数通过Client端上传文件时设置,文件上传成功后副本数可以变更,Block Size不可变更。
NameNode(NN)
-NameNode主要功能:接受客户端的读写服务
NameNode保存metadate信息包括
文件owership和permissions
文件包含那些块
Block保存在哪个DataNode(由DataNode启动时上报)
-NameNode的metadate信息在启动后会加载到内存
metadata存储到磁盘文件名为“fsimage”
Block的位置信息不会保存到“fsimage”
edits记录对metadata的操作日志
SecondaryNameNode(SNN)
-它不是NN的备份(但可以做备份),它的主要工作是帮助NN合并editslog,减少NN启动时间。
-SNN执行合并时机
根据配置文件设置的时间间隔fs.checkpoint.period默认3600秒
根据配置文件设置edits log大小 fs.checkpoint.size 规定edits文件的最大值默认是64MB
DataNode(DN)
-存储数据(Block)
-启动DN线程的时候会向NN汇报block信息
-通过向NN发送心跳保持与其联系(3秒一次),如果NN 10分钟没有收到DN的心跳,则认为其已经lost,并copy其上的block到其它DN
Block的副本放置策略
-第一副本:放置在上传文件的DN;
如果是集群外提交,则随机挑选一台磁盘不太满,CPU不太忙的节点。
-第二副本:放置在于第一个副本不同的机架的节点上。
-第三个副本:与第二个副本相同机架的节点。
-更多副本:随机节点
HDFS文件权限
-与linux文件权限类似
r:read,w:write;x:execute,权限x对于文件忽略,对于文件夹表示是否允许访问其内容
-如果Linux系统用户zhangsan使用hadoop命令创建一个文件,那么这个文件在HDFS中owner就是zhangsan。
-HDFS的权限目的:阻止好人做错事,而不是阻止坏人做坏事。HDFS相信,你告诉我你是谁,我就认为你是谁。
安全模式
-namenode启动的时候,首先将映射文件(fsimage)载入内存,并执行编辑日志(edits)中的各项操作。
-一旦在内存中成功建立文件系统元数据的映射,则创建一个新的fsimage文件(这个操作不需要SecondaryNameNode)和一个空的编辑日志。
-此刻namenode运行在安全模式。即namenode的文件系统对于客户端来说是只读的。(显示目录,显示文件内容等。写、删除、重命名都会失败)。
-在此阶段Namenode收集各个datanode的报告,当数据块达到最小副本数以上时,会被认为是“安全”的,在一定比例(可设置)的数据块被确定为“安全”后,再过若干时间,安全模式结束。
-当检测到副本数不足的数据块时,该块会被复制直到达到最小副本数,系统中数据的位置并不是由namenode维护的,而是以块列表形式存储在datanode中。
HDFS安装
-伪分布式安装
-完全分布式安装
下载
解压
检查java和ssh的免密码登陆
修改core-site.xml
修改hdfs-site.xml
修改 masters文件和slaves文件
格式化namenode
Start-hdfs.sh启动
***********10 11 12 13 14hadoop1.2.1 安装视频***************************
Hadoop核心组件-MR
-Hadoop分布式计算框架(MapReduce)
MapReduce设计理念
-何为分布式计算
-移动计算,而不是移动数据。
MapR
Hadoop计算框架Shuffler
-在mapper和reducer中间的一个步骤
-可以把mapper的输出按照某种key值重新切分和组合成n份,把key值符合某种范围的输出送到特定的reducer那里去处理
-可以简化reducer过程
Hadoop计算框架shuffle过程详解
-每个map task都有一个内存缓冲区(默认是100MB),存储着map的输出结果
-当缓冲区快满的时候需要将缓冲区的数据以一个临时文件的方式存放到磁盘(Spill)
-溢写是由单独线程来完成,不影响往缓冲区写map结果的线程(spill.percent,默认是0.8)
-当溢写线程启动后,需要对这80MB空间内的key做排序(Sort)
input
|
|
V
|---------------|
|Runningmap task|
|---------------|
|
|
V
partition
|
|
V
|--------------|
|MemoryBuffer |
|--------------|
|
|
V
Spill:Sort & Combiner
|
|
V
|--------------|
|merge |
|--------------|
Hadoop计算框架shuffle过程详解
-假如client设置过Combiner,那么现在就是使用Combiner的时候了。将有相同key的key/value对的value加起来,减少溢写到磁盘的数据量。(reducel、word1、[8]).
-当整个map task结束后再对磁盘中这个map task产生的所有临时文件做合并(Merge),对于“word1”就是像这样的:{“world”,[5,8,2,...]},假如有Combiner,{world[15]},最终产生一个文件。
-reduce 从tasktracker copy数据
-copy过来的数据会先放入内存缓冲区中,这里的缓冲区大小要比map端的更为灵活,它基于JVM的heap size设置
-merge有三种形式:1)内存到内存 2)内存到磁盘3)磁盘到磁盘。merge从不同tasktracker上拿到的数据,{word[15,17,2]}
-参考博客:http://langyu.iteye.com/blog/992916
MapReduce是怎么解决负载均衡和数据倾斜问题的?
map不可能产生数据倾斜
reduce容易产生数据倾斜,设计好Partitions,就可以避免倾斜。
MapReduce的Split大小
-max.split(100M)
-min.split(10M)
-block(64M)
-max(min.split,min(max.split,block))
MapReduce的架构
-一主多从架构
-主JobTracker:
负责调度分配每一个子任务task运行于TaskTracker上,如果发现有失败的task就重新分配其任务到其他节点。每一个hadoop集群中只一个JobTracker一般它运行在
Master节点上。
-从TaskTracker
TaskTracker主动与JobTracker通信,接收作业,并负责直接执行每一个任务,为了减少网络带宽TaskTracker最好运行在HDFS的
DataNode上
程序实例:
WcMapper.java
import org.apache.hadoop.mapreduce.Mapper;
public class WcMapper extends Mapper<LongWritable,Text,Text,IntWritable>{
//每次调用map方法会传入split中一行数据key:该行数据所在文件中的位置下标,value:这行数据
protected void map(LongWritable key,Text value,Context context)throws IOException,InterruptedException{
String line = value.toString();
StringTokenizer st = new StringTokenizer(value.toString());
while(st.hasMoreTokens()){
String world = st.nextToken();
context.write(new Text(world),IntWritable(1));//map的输出
}
}
}
public class WcReduce extends Reduce<Text,IntWritable,Text,IntWritable>{
protected void reduce(Text arg0,Iterable<IntWritable> itertable,Context context) throws IOException,InterruptedException{
int sum = 0;
for(IntWritable i : iterable){
sum = sum + i.get();
}
context.write(key,new IntWritable(sum));
}
}
JobRun.java
public class JobRun{
public static void main(String[] args){
Configuration conf = new Configuration();
conf.set("mapred.job.tracker","node1:9001");
try{
Job job = new Job(conf);
job.setJarByClass(JobRun.class);
job.setMapperClass(WcMapper.class);
job.setReducerClass(WcReducer.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
//job.setNumReduceTasks(1);//设置reduce任务的个数
//mapreduce 输入数据所在的目录或者文件
FileInputFormat.addInputPath(job,new Path(otherArgs[0]));
FileOutputFormat.setOutputPath(job,new Path(otherArgs[1]));
System.exit(job.waitForCompletion(true)? 0 : 1);
}catch(Exception e){
e.printStackTrace();
}
}
}
执行:./hadoop jar /root/wc.jar com.bjsxt.mr.JobRun
--------------------------------------------
test.txt
hello hadoop world lucene abc
hdfs mapper reduce hadoop hello
world efg location
-------------------------------------
qq好友推荐
test2
hadoop hello
hdfs world
tom cat
cat dog
hello world
----------------------------
Test2Mapper.java
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;
public class Test2Mapper extends Mapper<LongWritable,Text,Text,Text>{
protected void map(LongWritable key,Text value,Context context) throws IOException,InterruptedException{
String line = value.toString();
StringTokenizer st = new StringTokenizer(line,"\t");
while(st.hasMoreTokens()){
String line = value.toString();
String[] ss = line.split("\t");
context.write(new Text(ss[0]),new Text(ss[1]));
context.write(new Text(ss[1]),new Text(ss[0]));
}
}
}
public class Test2Reduce extends Reducer<Text,Text,Text,Text>{
protected void reduce(Text key,Iterable<Text> i,Context arg2) throws IOException,InterruptedException{
Set<String> set = new HashSet<String>();
for(Text t:i){
set.add(t.toString());
}
if(set.size()>1){
for(Iterator j=set.iterator();j.hasNext();){
String name = (String)j.next();
for(int k = 0;k < set.iterator();k.hasNext();){
String other = (String)k.next();
if(!name.equals(other)){
arg2.write(new Text(name),new Text(other));
}
}
}
}
}
}
Hadoop2.0产生背景
-Hadoop 1.0中HDFS和MapReduce在高可用、扩展性等方面存在问题
-HDFS存在的问题
NameNode单点故障,难以应用于在线场景
NameNode压力过大,且内存受限,影响系统扩展性
MapRedue存在的问题
JobTracker访问压力大,影响系统扩展性
难以支持除MapReduce之外的计算框架,比如Spark、Storm等
-------------------------------------------
Hadoop 1.x 和 2.x |
|
HADOOP1.0 HADOOP2.0 |
MapReduce MapReduce Others |
HDFS YARN |
HDFS |
---------------------------------------- |
-Hadoop 2.x由HDFS、MapReduce和YARN三个分支构成;
HDFS:NN Federation、HA;
MapReduce:运行在YARN上的MR;
YARN:资源管理系统
HDFS 2.x
-解决HDFS1.0中单点故障和内存受限问题。
-解决单点故障
HDFS HA:通过主备NameNode解决
如果主NameNode发生故障,则切换到备NameNode上
-解决内存受限问题
HDFS Federation(联邦)
水平扩展,支持多个NameNode
每个NameNode分管一部分目录
所有NameNode共享所有DataNode存储资
-2.x仅是架构上发生了变化,使用方式不变
-对HDFS使用者透明
-HDFS 1.x中的命令和API扔可以使用
HDFS 2.0 HA
-主备NameNode
-解决单点故障
主NameNode对外提供服务,备NameNode同步主NameNode元数据,以待切换
所有DataNode同时向两个NameNode汇报数据块信息
-两种切换选择
手动切换:通过命令实现主备之间的切换,可以用HDFS升级等场合
自动切换:基于Zookeeper实现
-基于Zookeeper自动切换方案
Zookeeper FailoverController:监控NameNode健康状态,
并向Zookeeper注册NameNode
NameNode挂掉后,ZKFC为NameNode竞争锁,获得ZKFC锁的NameNode变为active
HDFS 2.x Federation
-通过多个namenode/namespace把元数据的存储和管理分散到多个节点中,使到namenode/namespace可以通过增加机器来进行水平扩展。
-能把单个namenode的负载分散到多个节点中,在HDFS数据规模较大的时候不会也降低HDFS的性能。可以通过多个namespace来隔离不同类型的应用,把不同类型应用的
HDFS元数据和管理分派到不同的namenode中。
YARN
-YARN:Yet Another Resource Negotiator;
-Hadoop 2.0新引入的资源管理系统,直接从MRv1演化而来的;
核心思想:将MRv1中JobTracker的资源管理和任务调度两个功能分开,分别由ResourceManager和ApplicationMaster进程实现
ResourceManager:负责整个集群的资源管理和调度
ApplicationMaster:负责应用程序相关的事务,比如任务调度,任务监控和容错等
-YARN的引入,使得多个计算框架可运行在一个集群中
每个应用程序对应一个ApplicationMaster
目前多个计算框架可以运行在YARN上,比如MapReduce、Spark、Storm等
MapReduce On YARN
-MapReduce On YARN:MRv2
-将MapReduce作业直接运行在YARN上,而不是由JobTracker和TaskTracker构建的MRv1系统中
-基本功能模块
YARN:负责资源管理和调度
MRAppMaster:负责任务切分、任务调度、任务监控和容错等
MapTask/ReduceTask:任务驱动引擎,与MRv1一致
-每个MapReduce作业对应一个MRAppMaster
MRAppMaster任务调度
YARN将资源分配给MRAppMaster
MRAppMaster进一步将资源分配给内部的任务
-MRAppMaster容错
失败后,由YARN重新启动
任务失败后,MRAppMaster重新申请资源
hadoop2.x 安装
vi /etc/hosts
scp /etc/hosts root@node2:/etc/hosts
scp /etc/hosts root@node3:/etc/hosts
scp /etc/hosts root@node4:/etc/hosts
scp ~/.ssh/id_dsa.pub root@node4:~/
免登陆:
ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa
cat ~/.ssh/id_dsa.pub>>~/.ssh/authorized_keys
安装JDK
tar -zxvf /hadoop-2.5.1.tar
ln -sf /root/hadoop-2.5.1 /home/hadoop-2.5
./hadoop-daemon.sh start journalnode
jps
ls
cd /opt/hadoop2/
./stop-dfs.sh
./start-dfs.sh
./hdfs dfs -put /root/...
i.修改dataDir=/opt/zookeeper
ii. server.1=hadoop1:2888:3888
server.2=hadoop2:2888:3888
server.3=hadoop3:2888:3888
c) 在dataDir目录中创建一个myid的文件,文件内容为1、2、3
4、配置hadoop中的slaves
5、启动三个zookeper:./zkServer.sh start
6 启动三个JournalNode:./hadoop-daemon.sh start journalnode
7、在其中一个namenode上格式化:hdfs namenode -format
8、把刚刚格式化之后的元数据拷贝到另外一个namenode上
a)启动刚刚格式化的namenode
b)在没有格式化的namenode上执行:hdfs namenode -bootstrapStandby
c)启动第二个namenode
9、在其中一个namenode上初始化zkfc:hdfs zkfc -formatZK
10、停止上面节点:stop-dfs.sh
11、全面启动:start-dfs.sh
yarn-site.xml
<configuration>
<property>
<name>yarn.resourcemanager.hostname</name>
<value>master</value>
</property>
<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>
</configuration>
-------------------------------
datanode节点
jps
DataNode
Jps
QuorumPeerMain
JournalNode
NodeManager
-------------------------------
data.txt
1949-10-01 14:21:02/t34℃
1949-10-02 14:01:02/t36℃
1950-01-01 11:21:02/t32℃
1950-10-01 12:21:02/t37℃
1951-12-01 12:21:02/t23℃
1950-10-02 12:21:02/t41℃
1950-10-03 12:21:02/t27℃
1951-07-01 12:21:02/t45℃
1951-07-02 12:21:02/t46℃
----------------------------
readme.txt
1、计算在1949-1955年,每年温度最高的时间。
2、计算在1949-1955年,每年温度最高前十天。
思路:
1、按照年份的升序排序,同时每一年中温度降序排序。
2、按照年份分组,每一年对应一个reduce任务
mapper输出:key 为封装对象,
目的:
自定排序
自定义分区
自定义分组
------------------------------------------------------------------------------------------------------------
KeyPair.java
package com.wd;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import org.apache.hadoop.io.WritableComparable;
public class KeyPair implements WritableComparable<KeyPair>{
private int year;
private int hot;
public int getYear(){
return year;
}
public void setYear(int year){
this.year = year;
}
public int getHot(){
return hot;
}
public void setHot(int hot){
this.hot = hot;
}
public void readFields(DataInput in) throws IOException{
this.year = in.readInt();
this.hot = in.readInt();
}
public void write(DataOutput out) throws IOException{
out.writeInt(year);
out.writeInt(hot);
}
public int compareTo(KeyPair o){
int res = Integer.compare(year,o.getYear());
if(res!=0){
return res;
}
return Integer.compare(hot,o.getHot());
}
public String toString(){
return year + "\t" + hot;
}
}
--------------------------------------------------------------------------------------------------
SortHot.java
package com.wd;
import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator;
public class SortHot extends WritableComparator{
public SortHot(){
super(KeyPair.class,true);
}
public int compare(WritableComparable a,WritableComparable b){
KeyPair o1 = (KeyPair)a;
KeyPair o2 = (KeyPair)b;
int res = Integer.compare(o1.getYear(),o2.getYear());
if(res!=0){
return res;
}
return -Integer.compare(o1.getHot(),o2.getHot());//降序排序
}
}
---------------------------------------------------------------------------------------------------------
FirstPartition.java
package com.wd;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Partitioner;
public class FirstPartition extends Partitioner<KeyPair,Text>{
public int getPartition(KeyPair key,Text value,int num){
return (key.getYear()*127)%num;
}
}
-------------------------------------------------------------------------------------------------------------
GroupHot.java
package com.wd;
import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.io.WritableComparator;
public class GroupHot extends WritableComparator{
public GroupHot(){
super(KeyPair.class,true);
}
public int compare(WritableComparable a,WritableComparable b){
KeyPair o1 = (KeyPair) a;
KeyPair o2 = (KeyPair) b;
return Integer.compare(o1.getYear(), o2.getYear());
}
}
---------------------------------------------------------------------------------------------------------------
RunJob.java
package com.wd;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
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;
//hadoop jar /home/cloudera/wd.jar com.wd.RunJob
public class RunJob{
public static SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
static class HotMapper extends Mapper<LongWritable,Text,KeyPair,Text>{
protected void map(LongWritable key,Text value,Context context) throws IOException,InterruptedException{
String line = value.toString();
System.out.println("line=" + line);
System.out.println("℃");
System.out.println("---------------------------------------");
String[] ss = line.split("/t");
System.out.println("ss=" + ss.length);
if(ss.length==2){
try{
Date date = SDF.parse(ss[0]);
System.out.println(date);
Calendar c = Calendar.getInstance();
c.setTime(date);
int year = c.get(1);
System.out.println("ss[1]" + ss[1]);
String hot = ss[1].substring(0,ss[1].indexOf("℃"));
System.out.print("hot=" + hot);
KeyPair kp = new KeyPair();
kp.setYear(year);
kp.setHot(Integer.parseInt(hot));
context.write(kp,value);
}catch(Exception e){
e.printStackTrace();
}
}
}
}
static class HotReduce extends Reducer<KeyPair,Text,KeyPair,Text>{
protected void reduce(KeyPair kp,Iterable<Text> value,Context context)throws IOException,InterruptedException{
for(Text v:value)
context.write(kp,v);
}
}
public static void main(String[] args){
Configuration conf = new Configuration();
try{
Job job = new Job(conf);
job.setJobName("hot");
job.setJarByClass(RunJob.class);
job.setMapperClass(HotMapper.class);
job.setReducerClass(HotReduce.class);
job.setMapOutputKeyClass(KeyPair.class);
job.setMapOutputValueClass(Text.class);
job.setNumReduceTasks(4);//reduce数量
job.setPartitionerClass(FirstPartition.class);
job.setSortComparatorClass(SortHot.class);
job.setGroupingComparatorClass(GroupHot.class);
FileInputFormat.addInputPath(job,new Path("hdfs://192.168.1.198:8020/wd/input/"));
FileOutputFormat.setOutputPath(job,new Path("hdfs://192.168.1.198:8020/wd/output3/"));
System.exit(job.waitForCompletion(true)?0:1);
}catch(Exception e){
e.printStackTrace();
}
}
}
-------------------------------------------------------------------------------------------------------
hdfs dfs -cat /usr/output/hot/part-r-00000 | head -n1
1、在新浪微博中给九阳豆浆机打广告。广告精准推送。找到那些关注豆浆机的人,这些用户登录之后弹出九阳广告。并且安装关注度由高到低排序。
关注度权重公式
W = TF * Log(N/DF)
TF:当前关键字在该片微博内容中出现次数
DF:当前的关键字在所有微博中出现微博条数,比如:九阳,在某条微博中出现了4次。指计算为一条。
N:微博总条数。
广告推送实例:
FirstReduce.java
//第一个job输出结果为:
//九阳-001 2
//九阳-002 1
//count 19223
public class FirstReduce extends Reducer<Text,IntWritable,Text,IntWritable>{
protected void reduce(Text arg0,Iterable<IntWritable> arg1,Context arg2) throws IOException,InterruptedException{
int sum = 0;
for(IntWritable i : arg1){
sum = sum + i.get();
}
if(arg0.equals(new Text("count"))){
System.out.println(arg0.toString() + "_____________" + sum)
}
arg2.write(arg0,new IntWritable(sum))
}
}
---------------------------------------------
FirstPartition.java
/**
* 如果key为count 单独一个分区
* 其他的key:平均分配三个区
* @author root
*
*/
public class FirstPartition extends HashPartitioner<Text,IntWritable>{
public int getPartition(Text key,IntWritable value,int reduceCount){
if(key.equals(new Text("count")))
return 3;
else
return super.getPartition(key,value,reduceCount-1);
}
}
---------------------------------------------
TwoMapper.java
//统计每个词的DF
public class TwoMapper extends Mapper<LongWritable,Text,Text,IntWritable>{
protected void map(LongWritable key,Text value,Context context) throws IOException,InterruptedException{
FileSplit fs = (FileSplit)context.getInputSplit();
if(!fs.getPath().getName().contains("part-r-00003")){
String[] v = value.toString().trim().split("\t");
if(v.length >= 2){
String[] ss = v[0].split("_");
if(ss.length >= 2){
String w = ss[0];
context.write(new Text(w),new IntWritable(1));
}
}else{
System.out.println(value.toString() + "----------------------");
}
}
}
}
---------------------------------------
TwoJob.java
public class TwoJob{
public static void main(String[] args){
Configuration config = new Configuration();
config.set("yarn.resourcemanager,hostname","192.168.1.198");
try{
Job job = new Job(config);
job.setJarByClass(TwoJob.class);
job.setJobName("webo2");
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
job.setMapperClass(TwoMapper.class);
job.setCombinerClass(TwoReduce.class);
job.setReduceClass(TwoReduce.class);
FileInputFormat.addInputPath(job,new Path("/usr/weibo/output"));
FileOutputFormat.setOutputPath(job,new Path("/usr/weibo/output"));
boolean f = job.waitForCompletion(true);
if(f){
System.out.println("执行job成功");
}
}catch(Exception e){
e.printStackTrace();
}
}
}
--------------------------------------------------
LastMapper.java
public class LastMapper extends Mapper<LongWritable,Text,Text,Text>{
public static Map<String,Integer> cmap = null;
public static Map<String,Integer> df = null;
//在map方法执行之前
protected void setup(Context context) throws IOException,InterruptedException{
if(cmap == null || cmap.size() == 0 || df == null || df.size())
URI[] ss = context.getCacheFiles();
if(ss != null){
for(int i=0;i<ss.length;i++){
URI uri = ss[i];
if(uri.getPath().endsWith("part-r-00003")){
Path path = new Path(uri.getPath());
BufferedReader br = new BufferedReader(new FileRead());
String line = br.readLine();
if(line.startsWith("count")){
String[] ls = line.split("\t");
cmap = new HashMap<String,Integer>();
cmap.put(ls[0],Integer.parseInt(ls[1].trim()))
}
br.close();
}else if(uri.getPath().endsWith("part-r-00000")){
df = new HashMap<String,Integer>();
Path path = new Path(uri.getPath());
BufferedReader br = new BufferedReader(new FileReader());
String line;
while((line = br.readLine()) != null){
String[] ls = line.split("\t");
df.put(ls[0],Integer.parseInt(ls[1],trim()));
}
br.close();
}
}
}
}
protected void map(LongWritable key,Text value,Context context) throws IOException,InterruptedException{
FileSplit fs = (FileSplit)context.getInputSplit();
if(!fs.getPath().getName().contains("part-r-00003")){
String[] v = value.toString().trim().split("\t");
if(v.length >= 2){
int tf = Integer.parseInt(v[1].trim());
String[] ss = v[0].split("_");
if(ss.length >= 2){
String w = ss[0];
String id = ss[1];
double s = tf*Math.log(cmap.get("count")/df.get(w));
NumberFormat nf = NumberFormat.getInstance();
nf.setMaximumFractionDigits(5);
context.write(new Text(id),new Text(w + ":" +nf.format))
}
}else{
System.out.println(value.toString() + "--------------------------");
}
}
}
}
-------------------------------------------
LastReduce.java
//第二个job输出的结果:
九阳 2223
豆浆 2344
LastJob.java
public static void main(String[] args){
Configuration config = new Configuration();
config.set("yarn.resourcemanager","192.168.1.198");
try{
Job job = new Job(config);
job.setJarByClass(LastJob.class);
job.setJobName("weibo3");
job.addCacheFile(new Path("/usr/weibo/output1/part-r-00003"));
job.addCacheFile(new Path("/usr/weibo/output1/part-r-00000"));
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(Text.class);
}
}
-----------------------hive------------------
Hive
Hive:数据仓库
Hive:解释器、编译器、优化器等
Hive运行时,元数据存储在关系型数据库里面。
1、Hive数据类型
hive -e 直接执行sql
hive -f /home/my/hive-script.sql 执行sql文件
hive -S -e 'select a.col from tab1 a' > a.txt 把结果重定向到一个文件中
create database_name
drop database_name
use database_name
yum install mysql-server
service mysqld start
netstat -nplt | grep 3306
create table t_emp(id int,name string,age int,dept_name string)
row format delimited
fields terminated by ',';
desc tablename;
create table dept_count(num int) partitioned by(dname string);
insert into table dept_count partition(dname='销售部') select dept_name,count(1) from t_emp where dname = '销售部' group by dept_name;
export table t_temp to '/usr/input/emp.txt';
create table t_stu(
userid int,
name string,
age int,
sex int,classid int)
row format delimited fields terminated by ','
stored as textfile;
)
create table t_class(
cid int,
name string,
teacher string)
row format delimited fields terminated by ','
stored as textfile;
load data inpath '/pub/student.txt' into table t_stu;