MapReduce 实现数据join操作
前段时间有一个业务需求,要在外网商品(TOPB2C)信息中加入 联营自营 识别的字段。但存在的一个问题是,商品信息 和 自营联营标示数据是 两份数据;商品信息较大,是存放在hbase中。他们之前唯一的关联是url。所以考虑用url做key将两者做join,将 联营自营标识 信息加入的商品信息中,最终生成我需要的数据;
一,首先展示一下两份数据的demo example
1. 自营联营标识数据(下面开始就叫做unionseller.txt)
http://cn.abc.www/product43675,1
http://cn.abc.www/product43710,0
(是两列的数据,其中第一列是url也即是join操作要使用的key,后面的0,1是表示自营联营标识,0表示自营,1表示联营)
2. 商品信息数据(下面开始叫做shangpin_hbase.txt)
ROWKEY=http://cn.abc.www/product43675^_
image:image_url@1375896006814=http://*/*.jpg^_
image:is_default_image@1375897937280=0^_
image:thumbnail@1375897937280=**^_
parser:attribute@1375896006814={
......
......
uri:url@1375896006814=http://www.baby.com.cn/product-35520^_
^^
(上面是一条商品数据的样例,使用的是spider团队提供的一个jar包从hbase中导出来的,但也是比较标准的模式,可以使用hbase中HBaseDocInputFormat的类进行读取,其中貌似笑脸的那些field separator和line separator实际上是不可见字符,这里主要是为了展示而用可见字符代替;处于隐私原因,将一些内容用*代替)
由于商品数据是在hbase里面的,所以首先将商品数据从hbase中dump出来,通过rowkey来访问hbase大致有两种方式:
1. 通过单个row key访问:即按照某个row key键值进行get操作;
2. 通过row key的range进行scan;在范围内进行扫描;
一般来说,scan的方式会快一些。由于商品数据集的数量较为庞大(会有2000多万条url的商品及属性),并且商品是以url(host反转的方式,例如http://cn.abc.www/product43675)作为rowkey进行存储的。所以采用scan的方式从hbase中取出上商品数据集。
接下来获取自营联营识别数据,由于自营联营标识在hbase中是没有的,是spider团队在进行商品数据dump的时候计算出来的,所以直接用python写个streaming程序从dump数据中取得url字段和自营联营标识就可以了。较为简单,略过,本文主要来讲解join操作和hbase字段解析的过程。
二,现在我们手头上有了shangpin_hbase.txt以及unionseller.txt下面就可以考虑实现join操作的mapreduce了。
用mapreduce实现join比较常见的有两种方法,map端join和reduce端join
1. Map端join所针对的场景是,两个要进行join的数据集中,其中一个非常大,另一个非常小,以至于我们可以将小的数据集放到内存中。这样我们可以将小数据集复制多份,每个运行map task的内存中都存在一份(可以使用hash table),这样map task可以只扫描大的数据,对于大数据中的每一条记录,去小数据中找到相应的key的数据,然后连接输出;如果想让小数据集复制到每个map task中,可以使用mapreduce提供的Distributed Cache机制。
2. Reduce端join是一种比较简单和容易想到的方式,适合的环境也更为普遍。基本思路是在mapper中为每一个记录打上标记,并且使用连接键作为map输出键,使键相同的记录能够被分到同一个reducer中。
Reduce端join比较简单,但缺点是两个数据集都要经过mapreduce的shuffle过程(里面涉及到写磁盘,归并排序,还有网络传输等)。所以reduce端的join操作,效率往往低些。本文采用简单一些的reduce端join的实现。
1. 首先是mapper编写,由于join操作至少有两份数据集,所以常需要使用mapReduce的MultipleInputs.addInputPath()来添加多个输入文件的路径。也需要两个mapper类来实现对不同数据集的处理,首先来看一下处理unionseller.txt的mapper程序:

由于unionseller.txt的每一行是以逗号分割的两列,所以只要用逗号将两者分隔开就好,得到作为连接键的url项lst[0]和自营联营识别标识项lst[1]。Map的的输出key是TextPair类型,输出value是Put类型。这两个重点说一下:
(1)TextPair类型
map的输出即reduce的输入,有相同key的数据会被运送到同一个reduce来处理。为了在reduce端能够区分unionseller.txt和shangpin_hbase.txt类型,在TextPair中增加了一个识别字段,unionseller.txt是 “0”,即new TextPair(lst[0],”0”);而shangpin_hbase.txt字段是”1”,这样在reduce端就可以有依据来区分数据的类型。
TextPair是一个自定义的数据类型,其包含两个成员变量,first和second,两个成员变量都是Hadoop自带的Text类型。自己实现自定义的Key是要有些限制的,原因是:
(a)Mapper会根据key进行hash操作来决定记录被分配到哪一个reducer中去;
(b)在MapReduce内部机制中,在Mapper以及Reducer阶段都涉及到将数据写到磁盘的IO操作(spill阶段)和根据key对数据进行排序的操作。所以这就要求Mapper中的key是可以比较的,并且key和value是都是可以序列化的。Hadoop对自带的数据类型(Text,IntWritable等)都实现了序列化方法和内置的比较方法,但是对于自定义类型,就必须自己去实现相应的接口,并且重写方法。TextPair代码如下:



由于key需要进行比较并且需要序列化,所以实现了WritableComparable接口,其中compareTo()是实现了比较的方法,而readFields和write方法则是用于序列化的,告诉hadoop怎样读和写自定义的数据结构。这里解决了对key比较和序列化的问题,那么mapper对数据进行分发(决定到将记录发送到哪个reduce)的操作该怎样实现,这个需要集成Partitioner类并重写getPartition方法,实现自己的分发策略。

这里面自己定义了hash方法。
(2)介绍完了TextPair类,说一下Put类型,说Put类型之前,先看下处理shangpin_hbase.txt的mapper实现:

Put类型是Hbase自带的一个类型,由于shangpin_hbase.txt是从Hbase中导出来的,需要Hbase中的HBaseDocInputFormat.class进行解析,解析之后会成为<ImmutableBytesWritable, Put>的键值对,所以Mapper的key和value分别为ImmutableBytesWritable和Put类型。Put的”row”就是这条数据的rowkey。Put本质上是一个<byte[], List<KeyValue>结构的map,其中KeyValue也是Hbase所定义的一个数据类型,KeyValue是将Hbase中timestamp,family,qualifier,value扁平化存储的数据结构,要细讲就多了,感兴趣的可以看一下hbase的源代码。本文在后面会一个将Put转化为String的代码。处理shangpin_hbase.txt的map输出的textpair的标识是”1”。
2. 两个Mapper的工作介绍完了,接下来就要编写Reducer了。想一想,Reducer的任务比较简单,含有同样key的数据都在一起了。只要根据”0”和”1”的,取出自营,联营的识别标识,然后将这个塞到商品信息中就好了。
但这里面还有一个坑,就是shuffle的group过程,其实MapReduce框架中,在Reduce之前有一个group操作,将数据进行分组,同一个分组的数据会在一次reduce函数中被处理。group默认会使用key的compareTo方法来进行分组操作,按照上面TextPair的compareTo方法,url相同的”0”和”1”数据是分不到一个group里面的。这样从业务逻辑上分析是有问题的,所以我们需要对group的比较方法进行调整,MapReduce框架中也可以自定义group的比较方法:

这里我们设置,只有url相同,数据就会被放到同一个group里面。
下面是Reduce的代码以及 将Hbase中Put类型转化为String的方法:


至此,这次join操作就讲完了。附件中有实例代码。其实这个需求实现起来也可以不使用这么多的自定义函数,只不过文章中的实现更有助于了解MapReduce的原理。
By the way,用hive实现join是更简单的。。。
MapReduce 实现数据join操作的更多相关文章
- Mapreduce中的join操作
一.背景 MapReduce提供了表连接操作其中包括Map端join.Reduce端join还有半连接,现在我们要讨论的是Map端join,Map端join是指数据到达map处理函数之前进行合并的,效 ...
- 案例-使用MapReduce实现join操作
哈喽-各位小伙伴们中秋快乐,好久没更新新的文章啦,今天分享如何使用mapreduce进行join操作. 在离线计算中,我们常常不只是会对单一一个文件进行操作,进行需要进行两个或多个文件关联出更多数据, ...
- 使用MapReduce实现join操作
在关系型数据库中,要实现join操作是非常方便的,通过sql定义的join原语就可以实现.在hdfs存储的海量数据中,要实现join操作,可以通过HiveQL很方便地实现.不过HiveQL也是转化成 ...
- 大数据mapreduce俩表join之python实现
二次排序 在Hadoop中,默认情况下是按照key进行排序,如果要按照value进行排序怎么办?即:对于同一个key,reduce函数接收到的value list是按照value排序的.这种应用需求在 ...
- Hadoop基础-MapReduce的Join操作
Hadoop基础-MapReduce的Join操作 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.连接操作Map端Join(适合处理小表+大表的情况) no001 no002 ...
- 0 MapReduce实现Reduce Side Join操作
一.准备两张表以及对应的数据 (1)m_ys_lab_jointest_a(以下简称表A) 建表语句: create table if not exists m_ys_lab_jointest_a ( ...
- mapreduce join操作
上次和朋友讨论到mapreduce,join应该发生在map端,理由太想当然到sql里面的执行过程了 wheremap端 join在map之前(笛卡尔积),但实际上网上看了,mapreduce的笛卡尔 ...
- MapReduce实现的Join
MapReduce Join 对两份数据data1和data2进行关键词连接是一个很通用的问题,如果数据量比较小,可以在内存中完成连接. 如果数据量比较大,在内存进行连接操会发生OOM.mapredu ...
- MapReduce三种join实例分析
本文引自吴超博客 实现原理 1.在Reudce端进行连接. 在Reudce端进行连接是MapReduce框架进行表之间join操作最为常见的模式,其具体的实现原理如下: Map端的主要工作:为来自不同 ...
随机推荐
- Date的那一大堆事儿--1
String perfTimeStr = "";// 统一设置日历格式 Calendar calendar = Calendar.getInstance(); calendar.s ...
- C#的对象内存模型
转载自:http://www.cnblogs.com/alana/archive/2012/07/05/2577893.html C#的对象内存模型: 一.栈内存和堆内存1.栈内存 由编译器自动分配和 ...
- 3D动画
先上一道菜 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF ...
- C#引用Office.word出错的解决办法-无法嵌入互操作类型“Microsoft.Office.Interop.Word.ApplicationClass” 【转】
本文章转自 suchso 1.系统找不到 Microsoft.Office.Interop.Word" "Could not load file or assembly 'Micr ...
- Jdk1.8+Eclipse+MySql+Tomcat开发Java应用的环境搭建
Java学习开发的入门教程,方便大家在学习java开发过程中掌握最基本的环境搭建 有视频,有真相 http://www.chuanke.com/1340360-164338.html jdk是操作系统 ...
- jquery UI datepicker时间控件的使用
参考: http://api.jqueryui.com/datepicker/#method-show 英文 http://www.helloweba.com/view-blog-168.html 中 ...
- Java 集合系列 04 LinkedList详细介绍(源码解析)和使用示例
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
- Quoted-printable 编码介绍、编码解码转换
求教,“=B9=A4=D7=F7=BC=F2=B1=A8” 这种是什么编码方式? Quoted-printable 可译为“可打印字符引用编码”.“使用可打印字符的编码”,我们收邮件,查看信件原始信息 ...
- Objective-C:Foundation框架-常用类-NSDictionary
与NSString.NSArray一样,NSDictionary是不可变的,其对应可变类型为NSMutableDictionary.其用法如下: #import <Foundation/Foun ...
- BZOJ3308 九月的咖啡店
Orz PoPoQQQ 话说这题还有要注意的地方... 就是...不能加SLF优化,千万不能加 n = 40000,不加本机跑出来2sec,加了跑出来40sec...[给跪了 /*********** ...