第8章 Hadoop再探讨
Hadoop是一种开源的大数据处理架构,广泛应用于大数据技术领域。然而,Hadoop在诞生之初,在架构设计和应用性能方面存在一些不足之处,随着其后续的发展过程,逐渐得到了改进和完善。Hadoop的优化和发展主要体现在两个方面:一方面是Hadoop自身核心组件MapReduce和HDFS的架构设计改进,另一方面是Hadoop生态系统其他组件的不断丰富。
首先,Hadoop的局限和不足主要包括架构设计和性能方面的问题,如单一故障点、扩展性、资源利用率等。为了改进这些问题,Hadoop不断进行优化和提升,以支持更多应用场景,提高集群可用性和资源利用率。
其次,在Hadoop自身核心组件方面的新发展包括HDFS2.0新特性和新一代资源管理调度框架YARN框架。HDFS2.0改进了HDFS的架构设计,提高了可靠性和性能,同时增加了一些新特性,如支持多命名空间和快照等。YARN框架则将资源管理和调度从MapReduce中分离出来,成为一个独立的组件,可支持更多的计算模型和应用。
最后,Hadoop生态系统中的新成员,如Pig、Tez和Kafka等,对Hadoop的局限进行了有效的改进,进一步丰富和发展了Hadoop生态系统。这些组件提供了更高效的数据处理和管理方式,增强了Hadoop在实际应用中的功能和性能。
总之,随着Hadoop不断地优化和发展,它可以支持更多的应用场景,提供更高的集群可用性和资源利用率,并且其生态系统也在不断地丰富和发展。
8.1 Hadoop的优化与发展
8.1.1 Hadoop的局限与不足
Hadoop1.0的核心组件包括MapReduce和HDFS,但存在一些不足。
首先,抽象层次低,需要手工编写大量的代码来完成简单的功能;
其次,表达能力有限,MapReduce只提供了Map和Reduce两个函数,无法满足复杂应用需求;
第三,开发者需要自己管理作业之间的依赖关系,缺乏有效的管理机制;
第四,程序整体逻辑难以看到,给代码理解和维护带来障碍;
第五,执行迭代操作效率低,每次迭代都需要读写HDFS文件,降低了效率;
第六,Reduce任务需要等待所有Map任务完成后才能开始,造成不必要的资源浪费;
最后,Hadoop1.0只适用于离线批数据处理,无法支持实时数据处理和交互式数据处理。
这些不足制约了Hadoop1.0在实际应用中的性能和可用性。
8.1.2 针对Hadoop的改进与提升
针对Hadoop1.0存在的局限和不足,Hadoop经过后续的发展过程中对MapReduce和HDFS进行了多方面的改进和提升。
这些改进包括增加了更高层次的抽象机制,如YARN和MapReduce 2.0,使得编写代码更加简单和易于理解;同时采用了更加高效的存储系统,比如HBase和Cassandra,以及更加灵活的编程框架,如Spark和Flink,使得Hadoop的功能更加完善。
此外,在Hadoop生态系统中也融入了更多的新成员,如Pig、Oozie、Tez、Kafka等,这些产品提供了更加高级的数据操作和流程管理功能,进一步提升了Hadoop的性能和可用性。
Hadoop框架自身的改进:从1.0到2.0
不断完善的Hadoop生态系统
8.2 HDFS2.0的新特性
相对于之前的HDFS1.0而言,HDFS2.0增加了HDFS HA和HDFS联邦等新特性。
8.2.1 HDFS HA
HDFS是分布式文件系统,其中NameNode是核心节点,负责存储元数据信息、管理文件系统的命名空间和客户端对文件的访问。但是在HDFS1.0中只有一个NameNode,一旦发生故障就会导致整个集群不可用,这就是所谓的“单点故障问题”。虽然存在第二名称节点,但它不是备用节点,只是周期性地从NameNode获取命名空间镜像文件和修改日志,进行合并后再发送给NameNode,以防止日志文件过大导致恢复时间过长。但是第二名称节点无法提供“热备份”功能,即无法实时切换到备用节点立即对外提供服务,仍需要进行停机恢复,因此存在单点故障问题。
为了解决单点故障问题,HDFS2.0采用了HA(High
Availability,高可用性)架构。在HA集群中一般设置两个NameNode,一个处于活跃状态,另一个处于待命状态。活跃NameNode负责处理所有客户端请求,待命NameNode作为备用节点保存足够多的系统元数据,当活跃节点出现故障时提供快速恢复能力。因此,在HDFS HA中,待命节点提供了“热备份”,一旦活跃节点出现故障就可以立即切换到待命节点,不会影响系统的正常对外服务。
相当于强化了原来的第二名称节点
在HDFS HA架构中,由于待命名称节点是活跃名称节点的“热备份”,因此活跃名称节点的状态信息必须实时同步到待命名称节点。为了实现这个目标,可以借助于一个共享存储系统来实现,例如NFS(Network File System)、QJM(Quorum Journal Manager)或者Zookeeper。活跃名称节点将更新数据写入到共享存储系统,待命名称节点会一直监听该系统,一旦发现有新的写入,就立即从公共存储系统中读取这些数据并加载到自己的内存中,从而保证与活跃名称节点状态完全同步。
另外,名称节点中保存了数据块(Block)到实际存储位置的映射信息,即每个数据块是由哪个数据节点存储的。当一个数据节点加入HDFS集群时,它会把自己所包含的数据块列表报告给名称节点,并通过“心跳”的方式定期执行这种告知操作,以确保名称节点的块映射是最新的。为了实现故障时的快速切换,必须保证待命名称节点一直包含最新的集群中各个块的位置信息。为了做到这一点,需要给数据节点配置两个名称节点的地址(即活跃名称节点和待命名称节点),并把块的位置信息和心跳信息同时发送到这两个名称节点。
为了防止出现“两个管家”现象,HA还要保证任何时刻都只有一个名称节点处于活跃状态,否则,如果有两个名称节点处于活跃状态,HDFS集群中就会出现“两个管家”,导致数据丢失或者其他异常。这个任务由Zookeeper来实现,Zookeeper可以确保任意时刻只有一个名称节点提供对外服务。
8.2.2 HDFS联邦
1.HDFS1.0中存在的问题
HDFS1.0采用单名称节点的设计,存在单点故障、可扩展性、性能和隔离性等问题。单个名称节点保存整个文件系统的元数据信息,无法水平扩展,内存空间有上限,限制了文件、数据块和目录的数目。
纵向扩展虽然增加CPU和内存资源,但会导致过长的系统启动时间,而且内存空间清理错误可能导致整个集群宕机。整个文件系统的性能受限于单个名称节点的吞吐量,单个名称节点难以提供不同程序之间的隔离性,一个程序可能会影响其他程序的运行。
HDFS HA虽然提供了两个名称节点,但本质上还是单名称节点,只是通过“热备份”解决单点故障问题。但是,它并没有解决可扩展性、系统性能和隔离性三个方面的问题。在某个时刻,只有一个名称节点处于活跃状态,另一个处于待命状态。
因此,单个名称节点难以提供足够的可扩展性、系统性能和隔离性,限制了HDFS的应用场景和规模。为了解决这些问题,后续版本的HDFS引入了多名称节点和其他技术,如YARN、Hadoop 3.x等,以提高HDFS的可扩展性、性能和隔离性。
2.HDFS联邦的设计
HDFS联邦采用多个相互独立的名称节点的设计,使得HDFS的命名服务能够水平扩展,解决了单一名称节点的可扩展性和性能瓶颈问题。这些名称节点是相互独立的,不需要彼此协调,它们之间是联邦关系。相比于真正的分布式设计,HDFS联邦的实现和管理复杂度要低得多,同时可以快速满足需求。在兼容性方面,HDFS联邦具有良好的向单名称节点架构的兼容性,可以无缝地支持原有的部署配置。
在HDFS联邦中,每个名称节点提供命名空间和块管理功能,并共享底层数据节点的存储资源。每个数据节点需要向集群中所有的名称节点注册,并周期性地向名称节点发送“心跳”和块信息,报告自己的状态,同时也会处理来自名称节点的指令。
与HDFS1.0不同的是,HDFS联邦拥有多个独立的命名空间,每个命名空间管理属于自己的一组块,这些块构成一个“块池”。每个数据节点为多个块池提供块的存储,一个块池是一组块的逻辑集合,而实际上这些块可能存储在各个不同的数据节点中。因此,HDFS联邦中的一个名称节点失效,也不会影响到与它相关的数据节点继续为其他名称节点提供服务。
一个名称节点失效,会有别的名称节点接管其管理的块,将这些块放到自己的块池中。受到故障名称节点管理的块可能会发生一些短暂的不可用,但是整个HDFS集群仍然可以继续工作。
3.HDFS联邦的访问方式
HDFS联邦中的多个命名空间可以通过客户端挂载表(Client Side Mount Table)的方式进行数据共享和访问。每个阴影三角形代表一个独立的命名空间,客户可以访问不同的挂载点来访问不同的子命名空间。这种方式实现了命名空间的全局共享,即把各个命名空间挂载到全局的挂载表中。同时,命名空间也可以挂载到个人的挂载表中,成为应用程序可见的命名空间。这样,客户可以通过不同的挂载点访问不同的命名空间,实现了数据的全局共享和访问。这是HDFS联邦中命名空间管理的基本原理。
4.HDFS联邦相对于HDFS1.0的优势
采用HDFS联邦的设计方式可以解决单名称节点存在的三个问题:
首先,多个名称节点各自分管一部分目录,使得一个集群可以扩展到更多节点,从而实现了HDFS集群的可扩展性,不再受到内存限制的制约。
其次,多个名称节点管理不同的数据,且同时对外提供服务,这将为用户提供更高的读写吞吐率,从而提高了性能的效率。
另外,用户可以根据需要将不同业务数据交由不同名称节点管理,从而实现了良好的隔离性,不同业务之间的影响很小。
需要注意的是,HDFS联邦并不能解决单点故障问题。尽管使用了多个名称节点,但每个名称节点仍然存在单点故障的问题。为了应对名称节点宕机对业务造成的影响,需要为每个名称节点部署一个后备名称节点,以确保在名称节点宕机时能够及时接管故障名称节点的工作,从而保证HDFS集群的正常运行。
HDFS联邦并不能解决单点故障问题,HA那样的两个节点就可以解决单点故障,因为HA架构的备用节点用的热备份的方式备份数据,单论HDFS联邦的备份节点,就当它默认是冷备份吧。为每个NameNode配置HA,就说是HDFS联邦和HDFS HA的整合,那样就可以解决单点故障问题。
HDFS Federation和HA是两个独立的特性,它们分别解决了HDFS的扩展性和高可用性问题。HDFS Federation通过使用多个NameNode来扩展命名空间,而HA通过使用两个NameNode(一个Active,一个Standby)和共享存储来实现快速故障切换。这两个特性可以单独使用,也可以整合使用,具体取决于用户的需求。有些用户可能只需要扩展命名空间,而不需要高可用性;有些用户则需要同时解决这两个问题。因此,在设计时没有直接将这两个特性整合在一起,而是让用户根据自己的需求来选择是否整合使用。配置和维护HA需要额外的资源和成本,如果用户并不需要高可用性,那么这些资源和成本就浪费了。
8.3 新一代资源管理调度框架YARN
8.3.1 MapReduce1.0的缺陷
MapReduce 1.0采用了Master/Slave架构,其中包括一个JobTracker和若干个TaskTracker。JobTracker负责作业调度和资源管理,而TaskTracker负责执行具体任务。然而,这种架构设计存在一些难以克服的缺陷。
首先,由于系统中只有一个JobTracker负责所有MapReduce作业的调度,因此存在单点故障问题。如果JobTracker出现故障,整个系统将不可用。
其次,JobTracker需要执行大量任务,包括作业调度、失败恢复和资源管理分配。这会消耗大量资源,例如当存在大量MapReduce任务时,JobTracker需要巨大的内存开销。这也增加了JobTracker失败的风险。
此外,在TaskTracker端,资源分配并不考虑CPU和内存的实际使用情况,而是根据MapReduce任务的数量来分配资源。当两个内存消耗较大的任务被分配到同一个TaskTracker上时,很容易发生内存溢出。
最后,资源被强制划分为多个“槽”,并进一步划分为Map槽和Reduce槽。彼此之间不能使用对方的槽。这意味着当系统中只存在单一Map任务或Reduce任务时,当Map任务已经用完Map槽时,即使系统中还有大量剩余的Reduce槽,也不能拿来运行Map任务,会造成资源浪费。
8.3.2 YARN设计思路
Hadoop 2.0 以后的版本对 MapReduce1.0 版本的体系结构进行了重新设计,生成了 MapReduce2.0 和 YARN(Yet Another Resource Negotiator,另一种资源协调器)。YARN 的设计思路是“放权”,即把原本由 JobTracker 承担的三大功能(资源管理、任务调度和任务监控)进行拆分,分别交给不同的新组件去处理。重新设计后,YARN 包括了ResourceManager、ApplicationMaster 和 NodeManager三个组件。
ResourceManager 负责资源管理,即分配和管理集群中的资源。ApplicationMaster 负责任务调度和监控,即负责协调和管理任务的执行。最后,NodeManager 负责执行原来 TaskTracker 的任务,即在每个节点上运行任务并报告任务的状态。
通过这种“放权”的设计,YARN 大大降低了 JobTracker 的负担,提升了系统运行的效率和稳定性。每个组件都专注于自己的任务,相互之间不会互相干扰。同时,这种设计还使得 YARN 更加灵活,可以支持更多的应用程序。
在 Hadoop 1.0 中,其核心子项目MapReduce1.0 同时是一个计算框架和一个资源管理调度框架。这意味着 MapReduce1.0 既能够进行分布式计算,也能够管理和调度集群中的资源。然而,随着 Hadoop 的发展和应用场景的变化,MapReduce1.0 的这种设计逐渐暴露出了一些问题。
为了解决这些问题,在 Hadoop 2.0 以后的版本中,MapReduce1.0 中的资源管理调度功能被单独分离出来形成了 YARN。YARN 是一个纯粹的资源管理调度框架,不再具备计算功能。而被剥离了资源管理调度功能的 MapReduce 框架则变成了 MapReduce2.0。它是运行在 YARN 之上的一个纯粹的计算框架,不再自己负责资源调度管理服务,而是由 YARN 为其提供资源管理调度服务。
这种设计的好处是,将计算和资源管理调度分离开来,使得计算框架和资源管理调度框架可以独立演进和优化。同时,YARN 的出现也为 Hadoop 提供了更多的应用场景。任何需要进行资源管理调度的分布式应用都可以在 YARN 上运行,并且可以通过 YARN 的插件机制来扩展其功能。
8.3.3 YARN体系结构
如 图 8-6 所 示, YARN 体 系 结 构 中 包 含 了 三 个 组 件: ResourceManager、
ApplicationMaster和NodeManager。YARN各个组件的功能见表8-3。
图8-6 YARN体系结构
表8-3 YARN各个组件的功能
ResourceManager(RM)是一个全局的资源管理器,它主要由两个组件——调度器(Scheduler)和应用程序管理器(Applications Manager)组成。
调度器负责资源管理和分配,根据容量、队列等限制条件,把集群中的资源以“容器”的形式分配给提出申请的应用程序。应用程序管理器负责系统中所有应用程序的管理工作,包括应用程序提交、与调度器协商资源以启动 ApplicationMaster、监控 ApplicationMaster 运行状态并在失败时重新启动等。
在Hadoop平台上,用户的应用程序是以作业(Job)的形式提交的,然后一个作业会被分解成多个任务(包括Map任务和Reduce任务)进行分布式执行。ResourceManager接收用户提交的作业,按照作业的上下文信息以及从NodeManager收集来的容器状态信息,启动调度过程,为用户作业启动一个 ApplicationMaster。ApplicationMaster 的主要功能是:与 ResourceManager 协商获取资源,把获得的资源进一步分配给内部的各个任务,与 NodeManager 保持交互通信进行应用程序的启动、运行、监控和停止,监控申请到的资源的使用情况,对所有任务的执行进度和状态进行监控,并在任务发生失败时执行失败恢复,定时向 ResourceManager 发送“心跳”消息,报告资源的使用情况和应用的进度信息。当作业完成时,ApplicationMaster 向 ResourceManager 注销容器,执行周期完成。
NodeManager是驻留在一个YARN集群中的每个节点上的代理,主要负责容器生命周期管理,监控每个容器的资源使用情况,跟踪节点健康状况,并以“心跳”的方式与ResourceManager保持通信,向ResourceManager汇报作业的资源使用情况和每个容器的运行状态,同时,它还要接收来自 ApplicationMaster 的启动/停止容器的各种请求。
需要注意的是,NodeManager主要负责管理抽象的容器,而不负责每个任务自身状态的管理,因为这些管理工作是由ApplicationMaster完成的。NodeManager驻留在YARN集群中的每个节点上,负责容器的生命周期管理、监控每个容器的资源使用情况、跟踪节点健康状况,并通过“心跳”与ResourceManager保持通信,向ResourceManager汇报作业的资源使用情况和每个容器的运行状态。
同时,NodeManager还要接收来自ApplicationMaster的启动和停止容器的请求,但并不负责具体每个任务(Map任务或Reduce任务)自身状态的管理。YARN中的容器代表了CPU、内存、网络等计算资源,它也是和HDFS的数据节点一起部署的。在集群部署方面,YARN的各个组件是和Hadoop集群中的其他组件进行统一部署的。例如,YARN的ResourceManager组件和HDFS的名称节点(NameNode)部署在同一个节点上,而YARN的ApplicationMaster及NodeManager则是和HDFS的数据节点(DataNode)部署在一起的。
图8-7 YARN和Hadoop平台其他组件的统一部署
8.3.4 YARN工作流程
YARN(Yet Another Resource Negotiator)是一个Hadoop 2.x的资源管理器,用于统一管理Hadoop集群中的计算和存储资源。YARN的工作流程包括8个步骤。
第一步,用户编写客户端应用程序,并向YARN提交应用程序。提交的内容包括ApplicationMaster程序、启动ApplicationMaster的命令、用户程序等。
第二步,YARN中的ResourceManager负责接收和处理来自客户端的请求。接到客户端应用程序请求后,ResourceManager中的调度器会为应用程序分配一个容器。同时,ResourceManager的应用程序管理器会与该容器所在的NodeManager通信,为该应用程序在该容器中启动一个ApplicationMaster。
第三步,ApplicationMaster被创建后会首先向ResourceManager注册,从而使得用户可以通过ResourceManager来直接查看应用程序的运行状态。接下来的步骤4~7是具体的应用程序执行步骤。
第四步,ApplicationMaster采用轮询的方式通过RPC协议向ResourceManager申请资源。
第五步,ResourceManager以“容器”的形式向提出申请的ApplicationMaster分配资源。一旦ApplicationMaster申请到资源后,就会与该容器所在的NodeManager进行通信,要求它启动任务。
这里的“容器”可能有多个
第六步,当ApplicationMaster要求容器启动任务时,它会为任务设置好运行环境(包括环境变量、JAR包、二进制程序等),然后将任务启动命令写到一个脚本中,最后通过在容器中运行该脚本来启动任务。
第七步,各个任务通过某个RPC协议向ApplicationMaster汇报自己的状态和进度,让ApplicationMaster可以随时掌握各个任务的运行状态,从而可以在任务失败时重新启动任务。
第八步,应用程序运行完成后,ApplicationMaster向ResourceManager的应用程序管理器注销并关闭自己。若ApplicationMaster因故失败,ResourceManager中的应用程序管理器会监测到失败的情形,然后将其重新启动,直到所有的任务执行完毕。
8.3.5 YARN框架与MapReduce1.0框架的对比分析
YARN框架是从MapReduce1.0框架发展而来的,它的客户端API和接口与MapReduce1.0基本保持兼容,因此原来针对Hadoop1.0开发的代码可以直接在Hadoop2.0平台上运行,不需要大的改动。
YARN框架将MapReduce1.0中的JobTracker和TaskTracker分别拆分成了三个组件:ResourceManager、ApplicationMaster和NodeManager。ResourceManager负责调度、启动每一个作业所属的ApplicationMaster,监控ApplicationMaster运行状态并在失败时重新启动。而作业内的不同任务的调度、监控、重启等,则交由专门为该作业启动的ApplicationMaster来负责,它承担了MapReduce1.0中JobTracker的“作业监控”功能。
相对于MapReduce1.0,YARN有以下优势:
大大减少了ResourceManager的资源消耗。MapReduce1.0中的JobTracker需要同时承担资源管理、任务调度和任务监控等三大功能,而YARN中的ResourceManager只需要负责资源管理,任务调度和监控重启工作交由ApplicationMaster来完成。由于每个作业都有关联的独立ApplicationMaster,所以监控任务分布化,不再像MapReduce1.0那样只集中在一个JobTracker上。
YARN是一个纯粹的资源调度管理框架,不仅支持MapReduce编程模型,还可以运行其他类型的计算框架。因为它的ApplicationMaster是可变更的,用户可以编写服务于不同计算框架的ApplicationMaster,使得不同计算框架可以在YARN框架上运行。
YARN中的资源管理比MapReduce1.0更高效。YARN采用容器为单位进行资源管理和分配,而不是槽,避免了MapReduce1.0中槽的闲置浪费情况,提高了资源利用率。
8.3.6 YARN的发展目标
YARN并不仅仅是为了解决MapReduce 1.0框架中的问题,它有更加宏伟的发展构想,即成为一个集群中统一的资源管理调度框架,为各种计算框架提供统一的资源管理调度服务。
在一个企业中,不同的业务应用场景会有不同的数据处理需求,因此需要使用不同的计算框架,比如MapReduce、Impala、Storm和Spark等。这些框架通常来自不同的开发团队,具有各自的资源调度管理机制。
为了避免不同类型应用之间互相干扰,企业需要把内部的服务器拆分成多个集群,每个集群运行不同的计算框架。这会导致集群资源利用率低,因为不同集群的负载水平分布不均衡,繁忙的集群无法将负载分发到空闲的集群上执行。此外,不同集群之间无法直接共享数据,增加了数据传输开销和运维成本。
因此,YARN的目标是实现“一个集群多个框架”,在一个集群上部署一个统一的资源调度管理框架YARN,在YARN之上可以部署其他各种计算框架,由YARN为这些计算框架提供统一的资源调度管理服务,实现集群资源共享和资源弹性收缩。目前可以运行在YARN之上的计算框架包括MapReduce、Spark、Storm和Tez等。
这种部署方式有效提高了集群的利用率,降低了运维成本。其他类似功能的资源管理调度框架还包括Mesos、Torca、Corona和Borg等。
8.4 Hadoop生态系统中具有代表性的功能组件
8.4.1 Pig
Pig是Hadoop生态系统的一个组件,提供了类似SQL的Pig Latin语言(包含Filter、GroupBy、Join、OrderBy等操作,同时也支持用户自定义函数),允许用户通过编写简单的脚本来实现复杂的数据分析,而不需要编写复杂的MapReduce应用程序。
Pig会自动把用户编写的脚本转换成MapReduce作业在Hadoop集群上运行,而且具备对生成的MapReduce程序进行自动优化的功能,所以用户在编写Pig程序的时候,不需要关心程序的运行效率,这就大大减少了用户编程时间。
因此,通过配合使用Pig和Hadoop,在处理海量数据时就可以实现事半功倍的效果,比使用Java、C++等语言编写MapReduce程序的难度要小很多,并且用更少的代码量实现了相同的数据处理分析功能。
Pig可以加载数据、表达转换数据以及存储最终结果,因此在企业实际应用中(见图8-10),Pig通常用于ETL(Extraction、Transformation、Loading)过程,即来自各个不同数据源的数据被收集过来以后,采用Pig进行统一加工处理,然后加载到数据仓库Hive中,由Hive实现对海量数据的分析。
需要特别指出的是,每种数据分析工具都有一定的局限性,Pig的设计和MapReduce一样,都是面向批处理的,因此Pig并不适合所有的数据处理任务,特别是当需要查询大数据集中的一小部分数据时,Pig仍然需要对整个或绝大部分数据集进行扫描,因此实现性能不会很好。
Pig在企业数据分析系统中的作用:
Pig语句通常按照如下的格式来编写:
● 通过LOAD语句从文件系统读取数据;
● 通过一系列“转换”语句对数据进行处理;
● 通过一条STORE语句把处理结果输出到文件系统中,或者使用DUMP语句把处理结果输出到屏幕上。
以下是一个采用Pig Latin语言编写的示例程序,用于对用户访问网站情况进行统计分析:
从文件系统中读取用户访问日志visits
visits = LOAD '/data/visits' AS (user:chararray, url:chararray, time:long);
根据网址url对用户访问数据进行分组
gVisits = GROUP visits BY url;
对于每个url,计算访问量
visitCounts = FOREACH gVisits GENERATE group AS url, COUNT(visits) AS visits;
从文件系统中读取用户信息urlInfo
urlInfo = LOAD '/data/urlInfo' AS (url:chararray, category:chararray, pRank:int);
对visitCounts和urlInfo表进行连接操作
visitCounts = JOIN visitCounts BY url, urlInfo BY url;
根据用户类别进行分组
gCategories = GROUP visitCounts BY category;
对于每个用户类别,取出访问量TOP10
topUrls = FOREACH gCategories {sortedUrls = ORDER visitCounts BY visits DESC;top10 = LIMIT sortedUrls 10;GENERATE FLATTEN(top10) AS (url:chararray, visits:long, category:chararray, pRank:int);}
把访问量排名信息写入文件系统
STORE topUrls INTO '/data/topUrls';
该程序包含以下步骤:
使用LOAD语句从文件系统中读取用户访问日志数据,并将其存储为一个三元组(用户、网址和时间)。使用GROUP语句根据网址对访问数据进行分组。
使用FOREACH语句计算每个网址的访问量,并将其存储为一个二元组(网址和访问量)。使用LOAD语句从文件系统中读取用户信息数据,并将其存储为一个三元组(网址、类别和排名)。使用JOIN语句将访问量数据和用户信息数据连接起来,生成一个四元组(网址、访问量、类别和排名)。
使用GROUP语句根据用户类别对访问量数据进行分组。使用FOREACH语句对于每个用户类别,将访问量数据按照访问量进行排序,并取出前10个网址作为该类别的TOP10网址。使用STORE语句将TOP10网址信息写入文件系统。
整个程序会被Pig自动转换成MapReduce任务,其中group by和join操作都涉及到Shuffle过程,包含了Map端和Reduce端。因此,在Map和Reduce两个阶段之间,group by和join操作的矩形框都存在重叠区域。
从Pig Latin脚本转化得到的MapReduce作业:
当数据查询只面向相关技术人员,并且需要即时处理时,使用Pig编写脚本是一种比较适合的选择。Pig可以快速运行处理并避免表的创建等相关操作。
目前,Pig在许多公司都得到了广泛应用。例如,在Yahoo!中,超过90%的MapReduce作业是由Pig生成的;在Twitter公司中,超过80%的MapReduce作业也是由Pig生成的;在Linkedin公司中,大多数的MapReduce作业也是由Pig生成的。
除此之外,Pig还被Salesforce、Nokia、AOL和comScore等公司广泛采用。因为Pig具有易用性、可扩展性和高效性等优点,能够帮助企业快速处理数据并提高数据处理效率。
8.4.2 Tez
Tez是一种支持DAG作业的计算框架,它源于MapReduce框架,核心思想是将Map和Reduce两个操作进一步进行拆分,即Map被拆分成Input、Processor、Sort、Merge和Output,Reduce被拆分成Input、Shuffle、Sort、Merge、Processor和Output等。经过分解后的这些元操作可以进行自由任意组合产生新的操作,经过一些控制程序组装后就可形成一个大的DAG作业。
通过DAG作业的方式运行MapReduce作业,提供了程序运行的整体处理逻辑,可以去除工作流当中多余的Map阶段,减少不必要的操作,提升数据处理的性能。因此,Hortonworks把Tez应用到数据仓库Hive的优化中,使得性能提升了约100倍。
举例来说,在Hive中执行数据分析的一段HiveQL语句,其功能是对三个表在公共属性上进行连接操作,并根据state属性进行分组,并统计每个分组的元组个数和平均价格。在MapReduce框架中执行时,需要采用三个MapReduce作业才能完成,每个作业完成以后都需要写入到分布式文件系统HDFS中,供下一个作业读取,这带来了较大的处理延迟。
而在Tez框架中执行时,只需要一个Tez作业就可以完成,处理全过程不需要把数据写入到HDFS中,可以直接在不同的Map和Reduce任务之间传输数据,同时也减少了一些不必要的MapReduce操作,从而大大提升了程序执行效率。
总之,Tez作为一种支持DAG作业的计算框架,可以帮助企业快速处理数据并提高数据处理效率,被广泛应用于数据处理领域。
SELECT a.state, COUNT(*), AVERAGE(c.price)
FROM a
JOIN b ON(a.id = b.id)
JOIN c ON(a.itemId = c.itemId)
GROUP BY a.state
在Hadoop2.0生态系统中,MapReduce、Hive、Pig等计算框架在执行数据分析时都需要以MapReduce任务的形式进行最终的执行。因此,Tez框架可以发挥重要的作用。它可以在YARN框架之上运行,并让MapReduce、Pig和Hive等计算框架运行在Tez框架之上。
这种方式可以借助于Tez框架实现对MapReduce、Pig和Hive等计算框架的性能优化,从而更好地解决现有MapReduce框架在迭代计算(如PageRank计算)和交互式计算方面存在的问题。
具体来说,Tez框架可以通过优化任务执行的过程,减少任务之间的等待时间和数据传输时间,从而提高任务执行的效率和速度。同时,Tez框架还支持动态任务调度、任务共享等功能,可以帮助计算框架更好地适应不同的工作负载和数据处理场景。
因此,使用Tez框架可以提高整个Hadoop生态系统的数据处理能力和效率,从而更好地满足大规模数据处理的需求。
Tez和支持实时交互式查询分析的产品(如Impala、Dremel和Drill等)在解决Hive、Pig延迟大、性能低等问题的思路上有所不同。这些产品的解决问题思路是抛弃MapReduce计算框架,不再将类似SQL语句的HiveQL或者Pig语句翻译成MapReduce程序,而是采用与商用并行关系数据库类似的分布式查询引擎,可以直接从HDFS或者HBase中用SQL语句查询数据,从而大大降低了延迟,很好地满足了实时查询的要求。
相比之下,Tez则不同。例如针对Hive数据仓库进行优化的“Tez+Hive”解决方案,仍采用MapReduce计算框架,但是对DAG的作业依赖关系进行了裁剪,并将多个小作业合并成一个大作业。这样做不仅可以减少计算量,而且可以大大减少写HDFS的次数。
Tez的优化思路是在保留MapReduce计算框架的基础上,通过优化任务执行的过程、减少任务之间的等待时间和数据传输时间等方式,从而提高任务执行的效率和速度,以解决Hive、Pig延迟大、性能低等问题,更好地满足大规模数据处理的需求。
总之,Tez框架在Hadoop2.0生态系统中具有重要作用,可以帮助MapReduce、Pig和Hive等计算框架优化性能和提高效率,同时支持动态任务调度、任务共享等功能,可以更好地适应不同的工作负载和数据处理场景。虽然Tez的优化思路与实时交互式查询分析的产品有所不同,但都是为了更好地满足大规模数据处理的需求,为用户提供更快速、高效、可靠的数据处理解决方案。
8.4.3 Kafka
Kafka是一种高吞吐量的分布式发布订阅消息系统,主要用于处理大规模数据流。Kafka最初是由LinkedIn公司开发,后来成为Apache基金会的顶级项目。Kafka采用分布式架构,将数据分散存储在多个节点上,保证了系统的高可用性和可扩展性。同时,Kafka采用基于磁盘的存储方式,可以存储大量数据,并且提供高效的读写性能。
与其他消息队列框架相比,Kafka具有非常优秀的性能表现。Kafka能够同时提供实时在线处理的低延迟和批量离线处理的高吞吐量,这使得它在大数据生态系统中得到广泛应用。Kafka常被用于处理海量日志、用户行为和网站运营统计等数据。同时,Kafka还可以用于构建实时流处理系统,例如通过将Kafka与Apache Storm、Apache Spark等流处理框架结合起来,可以实现实时数据流的处理和分析。
传统的关系数据库虽然能够满足企业对数据一致性和高效复杂查询的需求,但是无法有效处理各种不同类型的数据,例如非结构化的日志记录和图结构数据,同时面对海量大规模数据也存在性能限制。因此,各种专用的分布式系统涌现出来,例如离线批处理系统、NoSQL数据库、流计算框架、图计算框架和搜索系统等。这些系统专注于满足企业某一方面的业务需求,但是如何实现这些专用系统与Hadoop各个组件之间数据的导入导出仍然是一个问题。
Kafka可以作为数据交换枢纽,不同类型的分布式系统可以统一接入Kafka,实现和Hadoop各个组件之间的不同类型数据的实时高效交换。使用Kafka作为交换枢纽还可以解决不同系统之间的数据生产/消费速率不同的问题。例如在线上实时数据需要写入HDFS的场景中,可以先将线上数据写入Kafka,然后再导入到HDFS中。这样可以保证数据的实时性和一致性,并且不会对线上系统的性能产生影响。
总之,Kafka作为一种高性能、可扩展的分布式消息系统,可以为各种大规模数据处理系统提供高效的数据交换服务,同时也可以用于构建实时流处理系统。Kafka的应用范围非常广泛,包括日志收集、数据管道、实时流处理、事件驱动架构等。
分布式发布订阅消息系统是指消息的发布者和订阅者可以分布在不同的机器或节点上,通过消息中间件进行通信和交互。在这种架构下,消息中间件充当了消息的传输和分发的角色,可以支持多个消费者同时消费同一条消息,从而实现消息的广播、发布和订阅等功能。
Kafka作为数据交换枢纽