第一章 初识Hadoop
-
数据!数据!
”大数据胜于好算法。“意思是说对于某些应用,不论算法有多牛,基于小数据的推荐效果往往都不如基于大量可用数据的一般算法的推荐效果。
-
不仅仅是批处理
名词”Hadoop“有时被用于指代一个更大的、多个项目组成的生态系统,而不仅仅是HDFS和MapReduce。这些项目都属于分布式计算和大规模数据处理范畴。这些项目就包括了:
1.第一个提供在线访问的组件是HBase,一种使用HDFS做底层存储的键值存储模型。HBase不仅提供对单行的在线读/写访问,还提供对数据块读/写的匹操作。
2.Hadoop2中YARN是一个集群资源管理系统,允许任何一个分布式程序基于Hadoop集群的数据而运行。
-
相较于其他系统的优势
1.关系型数据库管理系统:
这里有两个问题:①为什么不用数据库来进行大规模数据分析?②为什么需要Hadoop?
答案来自于计算机硬盘的一个发展趋势:寻址时间的提升远远赶不上传输速率的提升。如果数据访问模式中包含大量的硬盘寻址,那么读取大量数据集就必然会花更长的时间(传输速率取决于硬盘的带宽,流数据读取模式主要取决于传输速率)。关系型数据库采用传统的B树结构(这种数据结构受限于寻址的速率),如果数据库系统只更新一小部分记录,那么是有优势的。但数据库系统如果有大量数据更新时,B树的效率就明显落后于MapReduce,因为需要使用“排序/合并”来重建数据库。在许多情况下,可以将MapReduce视为关系型数据库管理系统的补充。
MapReduce比较适合解决需要以批处理方式分析整个数据集的问题,尤其是一些特定目的的分析。RDBMS适用于索引后数据集的点查询和更新,建立索引的数据库系统能够提供对小规模数据的低延迟数据检索和快速更新。MapReduce适合一次写入,多次读取数据的应用,关系型数据库则更适合持续更新的数据集。
Hadoop和关系型数据库的另一个区别在于它们所操作的数据集的结构化程度。Hadoop对非结构化或半结构化数据非常有效,因为它是在处理数据时才对数据进行解释(读时模式),避免了RDBMS数据加载阶段带来的高开销,因为在Hadoop中仅仅是一个文件拷贝操作。
第二章 关于MapReduce
MapReduce是一种可用于数据处理的编程模型。MapReduce程序本质上是并行运行的,因此可以将大规模的数据分析任务分发给任何一个拥有足够多机器的数据中心。MapReduce的优势就在于处理大规模数据集。
原始数据→Map(键值对)→sort→Reduce(键值对)→output
MapReduce工作原理:
⓵实现一个map函数⓶实现一个reduce函数⓷运行作业
➀public void map(key,values,Context context)
{
context.write(key,values);//map的输出与reduce的输入类型匹配
}
②public void reduce(key,values,Context context)
{
context.write(key,values);//reduce的输出类型也与输入匹配
}
③创建Job对象。
Job job = new Job();
job.setJarByClass(type.class);//方法传入作业类型
job.setJobName();//设置作业名称
//构造Job对象后,指定输入和输出路径
FileInputFormat.addInputPath(job,new Path(...));
FileOutputFormat.setOutputPath(job,new Path(...));//这里也是reduce的输出路径,之前目录不应该存在(否则会覆盖掉数据)。
job.setMapperClass(type1.class);//这里参数是map函数的类型
job.setReduceClass(type2.class);//这里参数是reduce函数的类型
//最后输出job作业的键值
job.setOutputKeyClass(key.class);
job.setOutputValueClass(value.class);//其键值于reduce类型匹配
横向扩展:现在开始鸟瞰整个系统以及有大量输入时的数据流,为了实现横向扩展,我们需要把数据存储在分布式文件系统中。通过使用Hadoop资源管理系统YARN,Hadoop可以将MapReduce计算转移到存储有部分数据的各台机器上。
-
数据流
MapReduce作业是客户端需要执行的一个工作单元:它包括输入数据、MapReduce程序和配置信息。Hadoop将作业分成若干个任务来执行,其中包括两类人物:map任务和reduce任务。这些任务运行在集群的节点上,并通过YARN进行调度。如果一个任务失败,它将在另一个不同的节点上自动重新调度运行。
Hadoop将MapReduce的输入数据划分成等长的小数据块,成为输入分片或简称“分片”。对于大多数作业来说,一个合理的分片大小趋向于HDFS的一个块的大小,默认是128MB,不过可以针对集群调整这个默认值(对所有新建的文件),或在每个文件创建时指定。
Hadoop在存储有输入数据的节点上运行map任务,可以获得最佳性能,因为它无需使用宝贵的集群带宽资源。这就是所谓的“数据本地化优化”。最佳分片的大小应该与块大小相同:因为它是确保可以存储在单个节点上的最大输入块的大小。如果分片跨越两个数据块,那么对于任何一个HDFS节点,基本上都不可能同时存储这两个数据块,因此分片中的部分数据需要通过网络传输到map任务运行的节点。与使用本地数据运行整个map任务相比,这种方法显然效率更低。
map任务将其输出写入本地硬盘,而非HDFS。这是为什么?因为map的输出是中间结果:该中间结果由reduce任务处理后才产生最终输出结果,而且一旦作业完成,map的输出结果就可以删除。所以把map中间结果保存到HDFS上未免小题大做了。reduce任务并不具备数据本地化的优势,单个reduce任务的输入通常来自于所有mapper的输出。数据在reduce端合并,然后由用户定义的reduce函数处理。reduce的输出通常存储在HDFS中以实现可靠存储。
map任务和reduce任务之间的数据流称为shuffle(混洗),因为每个reduce任务的输入都来自许多map任务。shuffle调整混洗参数对作业总执行时间的影响非常大。最后当数据处理可以完全并行(即无需混洗时),可能会出现无reduce任务的情况。在这种情况下,唯一的非本地节点数据传输是map任务将结果写入HDFS。
-
combiner函数
集群上的可用带宽限制了MapReduce作业的数量,因此尽量避免map和reduce任务之间的数据传输是有利的。Hadoop允许用户针对map任务的输出指定一个combiner,combiner函数的输出作为reduce函数的输入。由于combiner属于优化方案,所以Hadoop无法确定要对一个指定的map任务输出记录调用多少次combiner。换而言之,不管调用combiner多少次,reducer的输出结果都是一样的。