hadoop中利用mapreduce统计--每日登陆系统的用户频次

Hadoop是什么?!

Hadoop是一个分布式系统架构,由Apache基金会所开发。

HadoopMapReduce及其分布式文件系统(HDFS)而出名,但Hadoop这个名字也用于一组相关项目的统称。这些相关项目都使用这个基础平台进行分布式计算和海量数据处理。

1、本次技术交流的目的

通过一个事例使大家明白什么是HDFS,什么是MapReduce

2Hadoop产生背景

2.1Hadoop项目创始人Doug Cutting

Doug CuttingLuceneNutch Hadoop等项目的发起人。

1985Cutting毕业于美国斯坦福大学。

Cutting事业的起步阶段大部分是在Xerox(美国施乐公司是全球最大数字与信息技术产品生产商,是一家全球500强企业。),这段时间让他在搜索技术的知识上有了很大提高。他花了四年时间搞研发,这四年中,他阅读了大量论文,同时自己发表了很多论文。

尽管XeroxCutting积累了不少技术知识,但他却认为,自己当时搞的这些研究只是纸上谈兵,没有人试验过这些理论的可实践性。于是,他决定勇敢地迈出这一步,让搜索技术可以为更多人所用。

1997年底Cutting开始以每周两天的时间投入,在家里试着用Java把这个想法变成现实,不久之后,Lucene诞生了。作为第一个提供全文文本搜索的开源函数库

2.2 Hadoop的诞生

Lucene诞生之后,Cutting再接再厉,在 Lucene的基础上将开源的思想继续深化。2004年,Cutting和同为程序员出身的Mike Cafarella决定开发一款可以代替当时的主流搜索产品的开源搜索引擎,这个项目被命名为Nutch。在此之前,Cutting所在的公司 Architext(其主要产品为Excite搜索引擎)因没有顶住互联网经济泡沫的冲击而破产,那时的Cutting正处在Freelancer的生涯中,所以他希望自己的项目能通过一种低开销的方式来构建网页中的大量算法。幸运的是,Google这时正好发布了一项研究报告,报告中介绍了两款Google为支持自家的搜索引擎而开发的软件平台。这两个平台一个是GFSGoogle File System用于存储不同设备所产生的海量数据;另一个是MapReduce,它运行在GFS之上,负责分布式大规模数据。基于这两个平台,Cutting最引人瞩目的作品——Hadoop诞生了

出于对时间成本的考虑,在从Architext离职四年后,Cutting决定结束这段Freelancer的生涯,找一家靠谱的公司,进一步完善 Hadoop的性能。他先后面试了几家公司,其中也包括IBM,但IBM似乎对他的早期项目Lucene更感兴趣,至于Hadoop则不置可否。就在此时,Cutting接受了当时Yahoo!搜索项目负责人Raymie Stata的邀请,于2006年正式加入Yahoo!。在Yahoo!有一支一百人的团队帮助他完善Hadoop项目,这期间开发工作进行得卓有成效。 不久之后,Yahoo!就宣布,将其旗下的搜索业务的架构迁移到Hadoop上来。两年后,Yahoo!便基于Hadoop启动了第一个应用项目 “webmap”——一个用来计算网页间链接关系的算法。Cutting的时任上司(后为Hortonworks CEOEric Baldeschwieler曾说:在相同的硬件环境下,基于Hadoopwebmap的反应速度是之前系统的33倍。

2.3、综合概括Hadoop发展简史

HadoopApache LuceneApache Nutch创始人Doug Cutting创建的,Lucene是一个广泛使用的文本搜索系统库,Apache Nutch是一个开源的网络搜索引擎。

Hadoop起源于Apache NutchNutch也是Lucene项目的一部分。

3Hadoop简介

HadoopApache开源组织的一个分布式计算开源框架,在很多大型网站上都已经得到了应用,如亚马逊、FacebookYahoo等。

Hadoop的框架最核心的设计是:HDFSMapReduceHDFS为海量的数据提供了存储,MapReduce为海量的数据提供了强大的计算能力。

3.1HDFS简介

Hadoop实现了一个分布式文件系统(Hadoop Distributed File System),简称HDFSHDFS有高容错的特点,并且设计用来部署在低廉的硬件上;而且它提供高吞吐量来访问应用程序的数据,适合那些有着超大数据集的应用程序。

3.2MapReduce简介

MapReduce是一种可用于数据处理的编程模型。该模型比较简单,但用于编写有用的程序并不简单。Hadoop可以运行由各种语言(Java,Ruby,PythonC++)编写的MapReduce程序。MapReduce程序本质上是并行运行的,因此可以将大规模的数据分析任务交给任何一个拥有足够多机器的运营商。MapReduce的优势在于处理大规模数据集。

MapReduce是一种线性可伸缩的编程模型。程序员编写两个函数,分别为map函数和reduce函数——每个函数定义一个键/值对集合到另一个键/值对集合的映射。

这些函数无需关注数据集和它所用集群的大小,因此可以原封不动地应用到小规模数据集或大规模的数据集上。更重要的是,如果输入的数据量是原来的两倍,那么运行的时间也需要两倍。但是如果集群是原来的两倍,作业的运行仍然与原来一样快SQL查询一般不具备该特性。

MapReduce的设计目标是服务于那些只需数分钟或数小时即可完成的作业,并且运行于内部通过高速网络连接的单一数据中心内,并且该数据中心内的计算机需要有可靠的、定制的硬件构成。

简而言之,Hadoop提供了一个可靠的共享存储和分析系统。纵然Hadoop还有其他功能,但这两部分是它的核心。

3.3Hadoop处理数据能力

182008_Ce0x_870039.jpg

3.4Hadoop集群物理架构——两级网络拓扑

182051_PTCU_870039.jpg

3.5Hadoop集群内部节点拓扑图

182129_h6ah_870039.jpg

3.6Hadoop特点

3.6.1、方便

Hadoop运行在由一般商用机器构建的大型集群上运行,或者如亚马逊弹性计算云(EC2)等云计算服务之上。

3.6.2、健壮

Hadoop致力于在一般商用硬件上运行,其架构假设硬件会频繁出现失效。它可以从容地处理大多数此类故障。

3.6.3、可扩展

Hadoop通过增加集群节点,可以线性地扩展以处理更大的数据集。

3.6.4、简单

Hadoop允许用户快速编写出高效的并行代码。

4 Hadoop集群内部交互

1-1解释了如何与Hadoop集群交互。Hadoop集群是在同一地点用网络互连的一组通用机器。数据存储和处理都发生在这个机器“云”中。不同的用户可以从独立的客户端提交计算“作业“到Hadoop,这些客户端可以是原理Hadoop集群的个人台式机。

182326_qdJj_870039.jpg


5 HDFSMapReduce在实际中的运用(使用MapReduce分析数据)

5.1 Map阶段和Reduce阶段

MapReduce任务过程被分为两个处理阶段:map阶段和reduce阶段。

每个阶段都以键/值对作为输入和输出,并由程序员选择它们的类型。程序员还需具体定义两个函数:map函数和reduce函数。

5.2、处理数据(统计71日每个用户登陆系统的次数)

以一个简单的MapReduce程序来说明mapreduce两个函数的数据处理流程。

5.3 Map阶段

原始日志文件内容如下:

182433_Jise_870039.jpg

5.3.1、分片

对原始日志文件分片,默认每片大小为64MB,每片对应一个Map任务。

假设原始日志文件有160MB。以默认分片大小为分片标准,我们可以分3数据块。

Eg:

数据块1

182514_Kdaz_870039.jpg

数据块2

182542_Dwgx_870039.jpg

数据块3

182606_qxBs_870039.jpg

下面以处理第一个数据块的Map为例,讲解map阶段处理过程。

5.3.2map函数处理分片阶段

1)、输入map(LongWritable key, Text value,

         Context context)方法中的数据表现形式如下

采用TextInputFormat作为输入类型,所以,键/值分别为:

键:输入行在文件中的字节偏移量。

值:输入行的内容,不包括任何终止符。

213309_Zlw4_870039.jpg

5.3.3map函数运行阶段

1)、map(LongWritable key, Text value,

         Context context)方法:

 

public class IPStatisticsMapper extends Mapper<LongWritable, Text,   Text, IntWritable>{

   Text   key1;

   IntWritable   value1 = new IntWritable(1);

   @Override

   protected void map(LongWritable key,   Text value,

         Context   context)

         throws IOException,   InterruptedException {

      String   s = value.toString();

      s   = s.substring(0, s.indexOf(" "));

      key1 = new Text(s);

      context.write(key1, value1); }}

5.3.4map函数执行完成输出数据到本地磁盘

map函数开始产生输出时,并不是简单地将它写到磁盘。这个过程更复杂,它利用缓冲的方式写到内存,并出于效率的考虑进行预排序。

 

1)、执行map(LongWritable key, Text value,

         Context context)方法,数据存到本地磁盘,数据表现形式如下:

213354_PyqC_870039.jpg

可看出,存到本地磁盘中的数据是经过排序的。从map输出到reduce输入阶段,不仅进行了排序,也进行了shuffle(混洗)的操作。混洗就是文件分区(partition)的过程。

5.4 Reduce阶段

5.4.1、将map阶段产生的本地文件数据输入到reduce函数阶段

1)、执行reduce(Text key, Iterable<IntWritable> value,

         Context context)方法

public class IPStatisticsReducer extends   Reducer<Text, IntWritable, Text, IntWritable>{

   IntWritable value2;

   @Override

   protected void reduce(Text key,   Iterable<IntWritable> value,

         Context context)

         throws IOException,   InterruptedException {

      Iterator<IntWritable>   iter = value.iterator();

      int v = 0;

      while(iter.hasNext()){

         v += iter.next().get();

      }

      value2 = new IntWritable(v);

      context.write(key, value2);

   }

}

 

2)、传入reduce(Text key2, Iterable<IntWritable> value2,

         Context context)方法中的数据,表现形式如下:

213437_jSwr_870039.jpg

5.4.2reduce函数执行完成输出数据到文件系统

1)、执行reduce(Text key, Iterable<IntWritable> value,

         Context context)方法,数据存到文件系统HDFS中,reduce函数输出结果如下:

213504_7gut_870039.jpg

5.5、运行MapReduce作业

public class IPStatisticsMR {

   public static void main(String[] args) throws IOException, ClassNotFoundException,   InterruptedException {

      Job job = new Job();

      final String INPUT_PATH = "hdfs://master:9000/mapreduce-example-data/ip_log.txt";

      final String OUTPUT_PATH =   INPUT_PATH.substring(0, INPUT_PATH.lastIndexOf("/")) + "/_output";

      FileInputFormat.addInputPath(job,   new Path(INPUT_PATH));

      FileOutputFormat.setOutputPath(job,   new Path(OUTPUT_PATH));

      job.setMapperClass(IPStatisticsMapper.class);

      job.setReducerClass(IPStatisticsReducer.class);

      //TextInputFormat输入是默认的InputFormat

//    job.setInputFormatClass(TextInputFormat.class);

/*    job.setMapOutputKeyClass(Text.class);

      job.setMapOutputValueClass(IntWritable.class);*/

      job.setOutputKeyClass(Text.class);

      job.setOutputValueClass(IntWritable.class);

//    job.setOutputFormatClass(TextOutputFormat.class);

      job.waitForCompletion(true); }}

到此,MapReduce分析数据过程完毕。

6、为什么要使用MapReduce

大多数分析任务需要以某种方式结合大部分数据共同完成分析任务,即从一个磁盘读取的数据可能需要和从另外99个磁盘中读取的数据结合使用。各种分布式系统允许结合多个来源的数据并实现分析,但保证其正确性是一个非常大的挑战。MapReduce提出了一个编程模型,该模型将上述磁盘读写的问题进行抽象,并转换为对一个数据集(由键/值对组成)的计算。与HDFS类似,MapReduce自身也具有较高的可靠性。

7、一个reduce任务的MapReduce数据流图解

虚线框表示节点,虚线箭头表示节点内部的数据传输,而实线箭头表示节点之间的数据传输。

213549_dCuP_870039.jpg

8、多个reduce任务的MapReduce数据流--图解

213620_Pfn2_870039.jpg

9、无reduce任务的MapReduce数据流--图解

213647_NPne_870039.jpg

10、附录:

10.1、常用文本输入

10.1.1TextInputFormat

TextInputFormat是默认的InputFormat。每条记录是一行输入。键是LongWritable类型,存储该行在整个文件中的字符偏移量。值是这行的内容,不包括任何终止符(换行符和回车符),它是Text类型的。

所以,如果Map任务对应的文本输入类型为TextInputFormat,则其key/value输入类型为<LongWritable, Text>

10.1.2KeyValueTextInputFormat

文件中的每一行是一个键/值对,使用分解符进行分隔,比如制表符。

通过key.value.separator.in.input.line属性来指定分隔符

10.1.3NLineInputFormat

通过TextInputFormatKeyValueTextInputFormat,每个mapper收到的输入行数不同。行数依赖于输入分片的大小和行的长度。

如果希望mapper收到固定行数的输入,则需要使用NLineInputFormat作为InputFormat

TextInputFormat一样,键是文件中行的字符偏移量,值是行本身。

通过mapred.line.input.format.linespermap属性控制N的值。




转载于:https://my.oschina.net/HIJAY/blog/308883

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值