系统环境
Linux Ubuntu 16.04
jdk-7u75-linux-x64
hadoop-2.6.0-cdh5.4.5
hadoop-2.6.0-eclipse-cdh5.4.5.jar
eclipse-java-juno-SR2-linux-gtk-x86_64
任务内容
在电商网站中,用户进入页面浏览商品时会产生访问日志,记录用户对商品的访问情况,现有goods_visit2表,包含(goods_id,click_num)两个字段,数据内容如下:
goods_id click_num
1010037 100
1010102 100
1010152 97
1010178 96
1010280 104
1010320 103
1010510 104
1010603 96
1010637 97
编写MapReduce代码,功能为根据商品的点击次数(click_num)进行降序排序,再根据goods_id升序排序,并输出所有商品。
输出结果如下:
点击次数 商品id
------------------------------------------------
104 1010280
104 1010510
------------------------------------------------
103 1010320
------------------------------------------------
100 1010037
100 1010102
------------------------------------------------
97 1010152
97 1010637
------------------------------------------------
96 1010178
96 1010603
任务步骤
1.切换到/apps/hadoop/sbin目录下,开启Hadoop。
cd /apps/hadoop/sbin
./start-all.sh
2.在Linux本地新建/data/mapreduce8目录。
mkdir -p /data/mapreduce8
3.在Linux中切换到/data/mapreduce8目录下,用wget命令从http://192.168.1.100:60000/allfiles/mapreduce8/goods_visit2网址上下载文本文件goods_visit2。
cd /data/mapreduce8
wget http://192.168.1.100:60000/allfiles/mapreduce8/goods_visit2
然后在当前目录下用wget命令从http://192.168.1.100:60000/allfiles/mapreduce8/hadoop2lib.tar.gz网址上下载项目用到的依赖包。
wget http://192.168.1.100:60000/allfiles/mapreduce8/hadoop2lib.tar.gz
将hadoop2lib.tar.gz解压到当前目录下。
tar zxvf hadoop2lib.tar.gz
4.首先在HDFS上新建/mymapreduce8/in目录,然后将Linux本地/data/mapreduce8目录下的goods_visit2文件导入到HDFS的/mymapreduce8/in目录中。
hadoop fs -mkdir -p /mymapreduce8/in
hadoop fs -put /data/mapreduce8/goods_visit2 /mymapreduce8/in
5.新建Java Project项目,项目名为mapreduce8
在mapreduce8项目下新建一个package包,包名为mapreduce,在mapreduce的package包下新建一个SecondarySort类
6.添加项目所需依赖的jar包,右键单击mapreduce8,新建一个文件夹hadoop2lib,用于存放项目所需的jar包
将/data/mapreduce8目录下,hadoop2lib目录中的jar包,拷贝到eclipse中mapreduce8项目的hadopo2lib目录下,选中hadoop2lib目录下所有jar包,并添加到Build Path中。
7.编写Java代码,并描述其设计思路
二次排序:在mapreduce中,所有的key是需要被比较和排序的,并且是二次,先根据partitioner,再根据大小。而本例中也是要比较两次。先按照第一字段排序,然后在第一字段相同时按照第二字段排序。根据这一点,我们可以构造一个复合类IntPair,他有两个字段,先利用分区对第一字段排序,再利用分区内的比较对第二字段排序。Java代码主要分为四部分:自定义key,自定义分区函数类,map部分,reduce部分。
自定义key的代码:
public static class IntPair implements WritableComparable<IntPair>
{
int first; //第一个成员变量
int second; //第二个成员变量
public void set(int left, int right)
{
first = left;
second = right;
}
public int getFirst()
{
return first;
}
public int getSecond()
{
return second;
}
@Override
//反序列化,从流中的二进制转换成IntPair
public void readFields(DataInput in) throws IOException
{
// TODO Auto-generated method stub
first = in.readInt();
second = in.readInt();
}
@Override
//序列化,将IntPair转化成使用流传送的二进制
public void write(DataOutput out) throws IOException
{
// TODO Auto-generated method stub
out.writeInt(first);
out.writeInt(second);
}
@Override
//key的比较
public int compareTo(IntPair o)
{
// TODO Auto-generated method stub
if (first != o.first)
{
return first < o.first ? 1 : -1;
}
else if (second != o.second)
{
return second < o.second ? -1 : 1;
}
else
{
return 0;
}
}
@Override
public int hashCode()
{
return first * 157 + second;
}
@Override
public boolean equals(Object right)
{
if (right == null)
return false;
if (this == right)
return true;
if (right instanceof IntPair)
{
IntPair r = (IntPair) right;
return r.first == first && r.second == second;
}
else
{
return false;