通过全局文件复制实现多数据源的Map端连接


在DataJoin实现多数据源reduce端连接的过程中,连接在reduce阶段才会进行,因此一些无效的数据在reduce的时候才能去除掉,这样做占用了通信带宽,虽然该方法比较通用,但是效率不高。
当数据源中有数据量较小的或者经过处理后数据量较小的数据源的时候,我们考虑使用全局文件复制的方法来实现map端连接。这个过程需要Hadoop缓存系统的支持。Hadoop提供了DistributedCache类来操作缓存系统。
下面我们来说下map()端连接的思想:首先将数据量较小的数据源加载到缓存系统中,在MapReduce框架进行map之前,从缓存系统将文件全部加载到内存中,由于数据量小,因此可以实现。
对那个大的文件进行MapReduce处理,在map()方法中将有相同主键和外键记录进行连接即可。此过程不需要reducer。
当然,并不是所有的数据源都是小数据量的,但是有些情况可以转化为小数据量。比如仅仅需要查询辽宁地区的顾客订单信息,就可以先对customers文件进行过滤,得到一个中间文件,这个中间文件可能就是一个小数据量的数据源。另一个解决办法就是,假设有两个数据源S和R(相对较小),将大数据源R横向切分为多个小的数据源Ri,可以先使用全局文件复制的方法对每个Ri与S进行连接,最后将结果合并起来以、得到最终结果。
当然,数据源也不仅仅都是两个,当我们有多于2个的数据源时,我们可以两两进行连接,以得到最终结果。
代码见代码文档。
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.filecache.DistributedCache;
import org.apache.hadoop.fs.Path;

import org.apache.hadoop.mapreduce.Mapper;
import java.util.*;
import java.io.*;
public class MapJoin {
	public static class MapClass extends Mapper<Object,Text,Text,Text>{
		private HashMap<String , String> customers =new HashMap<String,String>();
		public void setup(Context context){
			BufferedReader br=null;
			try{
				Path paths []=DistributedCache.getLocalCacheFiles(context.getConfiguration());
				
				if(paths !=null&&paths.length>0)
				{
					 br = new BufferedReader(new FileReader(paths[0].toString()));
					 String line=null;
					 while((line=br.readLine())!=null){
						customers.put(line.split(",",2)[0],line.split(",",2)[1]);
					 }
				}
				
			}catch(Exception e){e.printStackTrace();}
			finally{
				try{
					 br.close();
				}catch(Exception e){
					e.printStackTrace();
				}
			}
		}
		public void map(Object key,Text value,Context context) throws IOException,InterruptedException{
			String [] strs=value.toString().split(",",2);
			context.write(new Text(strs[0]), new Text(customers.get(strs[0])+","+strs[1]));
			
		
		}	
	}
	public static void main(String []  args) throws Exception
	{
		Configuration conf = new Configuration();
		Job job = new Job(conf);
		
		FileInputFormat.addInputPath(job,new Path("hdfs://master:9000/user/xuyizhen/in/order.txt"));
		FileOutputFormat.setOutputPath(job,new Path("hdfs://master:9000/user/xuyizhen/out"));
		//addCacheFile的第二个参数必须是JobConf而不是Job类
		DistributedCache.addCacheFile(new Path("hdfs://master:9000/user/xuyizhen/in/customer.txt").toUri(),job.getConfiguration());
		
		job.setJarByClass(MapJoin.class);
		job.setMapperClass(MapClass.class);
		job.setInputFormatClass(TextInputFormat.class);
		job.setOutputFormatClass(TextOutputFormat.class);
	    job.setNumReduceTasks(0);
		
		System.exit(job.waitForCompletion(true)?0:1);
	}

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值