全栈工程师开发手册(原创)

全栈工程师,前端工程师,后端工程师,架构师,爬虫工程师,数据分析师,大数据工程师,数据挖掘工程师,机器学习工程师,栾鹏全栈...

hadoop、hbase、hive、spark分布式系统架构原理

机器学习、数据挖掘等各种大数据处理都离不开各种开源分布式系统,hadoop用户分布式存储和map-reduce计算,spark用于分布式机器学习,hive是分布式数据库,hbase是分布式kv系统,看似互不相关的他们却都是基于相同的hdfs存储和yarn资源管理,

hadoop、spark、Hbase、Hive、hdfs简介

Hbase:是一个nosql数据库,和mongodb类似

hdfs:hadoop distribut file system,hadoop的分布式文件系统

Hive:hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件(或者非结构化的数据)映射为一张数据库表,并提供简单的sql查询功能,可以将sql语句转换为MapReduce任务进行运行。 其优点是学习成本低,可以通过类SQL语句快速实现简单的MapReduce统计,不必开发专门的MapReduce应用,十分适合数据仓库的统计分析。

使用Hive,就不用去写MapReduce,而是写sql语句就行了。

sqoop:sqoop是和Hive一起使用的。Sqoop(发音:skup)是一款开源的工具,主要用于在Hadoop(Hive)与传统的数据库(mysql、postgresql…)间进行数据的传递,可以将一个关系型数据库(例如 : MySQL ,Oracle ,Postgres等)中的数据导进到Hadoop的HDFS中,也可以将HDFS的数据导进到关系型数据库中。

使用sqoop导入数据至hive常用语句 :
直接导入hive表

     sqoop import --connect jdbc:postgresql://ip/db_name--username user_name  --table table_name  --hive-import -m 5 

内部执行实际分三部,1.将数据导入hdfs(可在hdfs上找到相应目录),2.创建hive表名相同的表,3,将hdfs上数据传入hive表中

这里写图片描述

分布式hadoop架构

hadoop分为几大部分:yarn负责资源和任务管理、hdfs负责分布式存储、map-reduce负责分布式计算

YARN资源任务调度

YARN总体上仍然是master/slave(主从)结构

ResourceManager是Master上一个独立运行的进程,负责集群统一的资源管理、调度、分配等等;NodeManager是Slave上一个独立运行的进程,负责上报节点的状态;App Master和Container是运行在Slave上的组件,负责应用程序相关事务,比如任务调度、任务监控和容错等,Container是yarn中分配资源的一个单位,包涵内存、CPU等等资源,yarn以Container为单位分配资源。

YARN的基本架构 ,YARN的架构设计使其越来越像是一个云操作系统,数据处理操作系统。

这里写图片描述

从YARN的架构来看,它主要由ResourceManager、 NodeManager、ApplicationMaster 和 Container组成

(1)ResourceManager(RM)
RM是一个全局的资源管理器,负责整个系统的 资源管理和分配。它主要由两个组件构成:调度器(Schedule)和应用程序管理器(Application Manager, ASM)

YARN分层结构的本质是ResourceManager。这个实体控制整个集群并管理应用程序向基础计算资源的分配。ResourceManager将各个资源部分(计算、内存、带宽等)精心安排给基础NodeManager(YARN的每节点代理)。ResourceManager还与ApplicationMaster一起分配每个应用程序内每个任务所需的资源,与NodeManager一起启动和监视它们的基础应用程序。在此上下文中,ApplicationMaster承担了以前的TaskTracker的一些角色,ResourceManager承担了JobTracker的角色。

a)调度器(Scheduler)
调度器根据容量、队列等限制条件(如每个队列分配一定的资源,最多执行一定数量的作业等),将系统中的资源分配给各个正在运行的应用程序。该调度器是一个“纯调度器”,它不再从事任何与具体应用程序相关的工作。,比如不负责监控或者跟踪应用的执行状态等,也不负责重新启动因应用执行失败或者硬件故障而产生的失败任务,这些均交由应用程序相关的ApplicationMaster完成。调度器仅根据各个应用程序的资源需求进行资源分配,而资源分配单位用一个抽象概念“资源容器”(Resource Container,简称Container)表示,Container是一个动态资源分配单位,它将内存、CPU、磁盘、网络等资源封装在一起,从而限定每个任务使用的资源量。此外,该调度器是一个可插拔的组件,用户可根据自己的需要设计新的调度器,YARN提供了多种直接可用的调度器,比如Fair Scheduler和Capacity Scheduler等。

b)应用程序管理器(Application Manager,ASM)
应用程序管理器负责管理整个系统中所有的应用程序,包括应用程序提交、调度协调资源以启动ApplicationMaster、监控ApplicationMaster运行状态并在失败时重新启动它。

(2)ApplicationMaster(AM)

ApplicationMaster管理一个在YARN内运行的应用程序的每个实例。

ApplicationMaster负责申请而获得的来自ResourceManager的资源,并通过NodeManager监视容器的执行和资源的使用(cpu、内存等资源分配)。

请注意,尽管目前的资源更加传统(CPU核心、内存),但未来会带来基于手头任务的新资源类型(比如图形处理单元,或专用处理设备)。从YARN角度来讲,ApplicationMaster使用户代码因此存在潜在安全问题。YARN假设ApplicationMaster存在错误或者甚至是恶意的,因此将它们当做无特权的代码对待。

AM功能:数据切分、为应用程序申请资源并进一步分配给内部任务、任务监控与容错

(3)NodeManager(NM)

NodeManager管理一个YARN集群中的每个节点。NodeManager提供针对集群中每个节点的服务,从监督对一个容器的终身管理到监视资源和跟踪节点健康。MRv1通过插槽管理Map和Reduce任务执行,而NodeManager管理抽象容器,这些容器代表着可供一个特定应用程序使用的针对每个节点的资源。YARN继续使用HDFS层。它的主要NameNode主要用于元数据服务,而DataNode用于分散在一个集群中的复制存储服务。
NM是每个节点上的资源和任务管理器。一方面,它会定时地向RM汇报本节点上的资源使用情况和各个Container运行状态;另一方面,它接收并处理来自AM的 Container 启动/停止等各种请求。

功能:单个节点上的资源管理和任务。处理来自于resourcemanager的命令。处理来自域ApplicationMaster的命令。

(4)Container
Container是YARN中的资源抽象,它封装了某个节点上的多维度资源,如内存,CPU,磁盘,网络等。当AM向RM申请资源时,RM为AM返回的资源便是用Container表示的。YARN会为每个任务分配一个Container,且该任务只能用该Container中描述的资源。(注意:ApplicationMaster获得的资源不一定是当前主机节点上的

应用程序在yarn上的调度流程

Client向ResourceManager提交的每一个应用程序都必须有一个Application Master,它经过ResourceManager分配资源后,运行于某一个Slave节点的Container中,每个应用程序包含多个任务task,每个任务同样也运行在某一个Slave节点的Container容器中(不一定和Application Master在同一个Slave节点中)。RM,NM,AM乃至普通的Container之间的通信,都是用RPC机制。

所以说:一个应用程序所需的Container分为两大类,如下:

(1) 运行ApplicationMaster的Container:这是由ResourceManager(向内部的资源调度器)申请和启动的,用户提交应用程序时,可指定唯一的ApplicationMaster所需的资源;

(2) 运行各类任务的Container:这是由ApplicationMaster向ResourceManager申请的,并由ApplicationMaster与NodeManager通信以启动之。

以上两类Container可能在任意节点上,它们的位置通常而言是随机的,即ApplicationMaster可能不与它管理的任务运行在一个节点上。

所以ResourceManager接收到一个应用程序的客户请求后,协商一个容器的必要资源,启动一个ApplicationMaster来表示已经提交的应用程序。ApplicationMaster开始管理该应用程序的执行,也就是该应用程序内多个任务的执行。ApplicationMaster向ResourceManager请求每个任务所需的资源,ResourceManager分配处于多个节点撒上的资源后,ApplicationMaster协商每个节点上供该应程序使用的资源容器。执行应用程序时,ApplicationMaster监视资源容器,直到完成。当应用程序完成时,ApplicationMaster从ResourceManager注销其容器,执行周期就完成了。

YARN的工作原理

这里写图片描述

来总结以下yarn的功能:

yarn的两个部分:资源管理、任务调度。

资源管理需要一个全局的ResourceManager(RM)和分布在每台机器上的NodeManager协同工作,RM负责资源的仲裁,NodeManager负责每个节点的资源监控、状态汇报和Container的管理

任务调度也需要ResourceManager负责任务的接受和调度,在任务调度中,在Container中启动的ApplicationMaster(AM)负责这个任务的管理,当任务需要资源时,会向RM申请,分配到的Container资源用来做任务,然后AM和这些Container做通信,管理任务的运行,AM和具体执行的任务都是在Container中执行的。

一个应用程序的运行过程如下:

步骤1:用户将应用程序提交到ResourceManager上;

步骤2:ResourceManager并与某个NodeManager通信,在节点的container中启动负责该应用程序的ApplicationMaster;

步骤3:ApplicationMaster与ResourceManager通信,为内部要执行的任务(一个应用程序包含多个任务)申请资源,一旦得到资源后,将与NodeManager通信,以启动对应的任务。

步骤4:所有任务运行完成后,ApplicationMaster向ResourceManager注销,整个应用程序运行结束。

ApplicationMaster当向ResourceManager申请资源,需向它发送一个ResourceRequest列表,其中,每个ResourceRequest描述了一个资源单元的详细需求,而ResourceManager则为之返回分配到的资源描述Container。每个ResourceRequest可看做一个可序列化Java对象,包含的字段信息(直接给出了Protocol Buffers定义)如下:

    message ResourceRequestProto {

    optional PriorityProto priority = 1; // 资源优先级

    optional string resource_name = 2; // 资源名称(期望资源所在的host、rack名称等)

    optional ResourceProto capability = 3; // 资源量(仅支持CPU和内存两种资源)

    optional int32 num_containers = 4; // 满足以上条件的资源个数

    optional bool relax_locality = 5 [default = true];  //是否支持本地性松弛(2.1.0-beta之后的版本新增加的,具体参考我的这篇文章:Hadoop新特性、改进、优化和Bug分析系列3:YARN-392)

    }

通过上面的信息也看出了,资源不一定在当前主机上。可以为应用程序申请任意大小的资源量(CPU和内存),且默认情况下资源是本地性松弛的,即申请优先级为10,资源名称为“node11”,资源量为<2GB, 1cpu>的5份资源时,如果节点node11上没有满足要求的资源,则优先找node11同一机架上其他节点上满足要求的资源,如果仍找不到,则找其他机架上的资源。而如果你一定要node11上的节点,则将relax_locality置为false。

发出资源请求后,资源调度器并不会立马为它返回满足要求的资源,而需要应用程序的ApplicationMaster不断与ResourceManager通信,探测分配到的资源,并拉取过来使用。一旦分配到资源后,ApplicatioMaster可从资源调度器那获取以Container表示的资源,Container可看做一个可序列化Java对象,包含的字段信息(直接给出了Protocol Buffers定义)如下:

    message ContainerProto {

    optional ContainerIdProto id = 1; //container id

    optional NodeIdProto nodeId = 2; //container(资源)所在节点

    optional string node_http_address = 3;

    optional ResourceProto resource = 4; //container资源量

    optional PriorityProto priority = 5; //container优先级

    optional hadoop.common.TokenProto container_token = 6; //container token,用于安全认证

    }

一般而言,每个Container可用于运行一个任务。ApplicationMaster收到一个或多个Container后,再次将该Container进一步分配给内部的某个任务,一旦确定该任务后,ApplicationMaster需将该任务运行环境(包含运行命令、环境变量、依赖的外部文件等)连同Container中的资源信息封装到ContainerLaunchContext对象中,进而与对应的NodeManager通信,以启动该任务。ContainerLaunchContext包含的字段信息(直接给出了Protocol Buffers定义)如下:

    message ContainerLaunchContextProto {

    repeated StringLocalResourceMapProto localResources = 1; //Container启动以来的外部资源

    optional bytes tokens = 2;

    repeated StringBytesMapProto service_data = 3;

    repeated StringStringMapProto environment = 4; //Container启动所需的环境变量

    repeated string command = 5; //Container内部运行的任务启动命令,如果是MapReduce的话,Map/Reduce Task启动命令就在该字段中

    repeated ApplicationACLMapProto application_ACLs = 6;

    }

每个ContainerLaunchContext和对应的Container信息(被封装到了ContainerToken中)将再次被封装到StartContainerRequest中,也就是说,ApplicationMaster最终发送给NodeManager的是StartContainerRequest,每个StartContainerRequest对应一个Container和任务。

hdfs分布式存储架构

HDFS即Hadoop Distributed File System分布式文件系统,它的设计目标是把超大数据集存储到分布在网络中的多台普通商用计算机上,并且能够提供高可靠性和高吞吐量的服务。分布式文件系统要比普通磁盘文件系统复杂,因为它要引入网络编程,分布式文件系统要容忍节点故障也是一个很大的挑战。

设计前提和目标

专为存储超大文件而设计:hdfs应该能够支持GB级别大小的文件;它应该能够提供很大的数据带宽并且能够在集群中拓展到成百上千个节点;它的一个实例应该能够支持千万数量级别的文件。
适用于流式的数据访问:hdfs适用于批处理的情况而不是交互式处理;它的重点是保证高吞吐量而不是低延迟的用户响应
容错性:完善的冗余备份机制
支持简单的一致性模型:HDFS需要支持一次写入多次读取的模型,而且写入过程文件不会经常变化
移动计算优于移动数据:HDFS提供了使应用计算移动到离它最近数据位置的接口
兼容各种硬件和软件平台

不适合的场景

大量小文件:文件的元数据都存储在NameNode内存中,大量小文件会占用大量内存。
低延迟数据访问:hdfs是专门针对高数据吞吐量而设计的
多用户写入,任意修改文件

hdfs架构设计

我们看一下hdfs的架构:hdfs部分由NameNode、SecondaryNameNode和DataNode组成。DataNode是真正的在每个存储节点上管理数据的模块,NameNode是对全局数据的名字信息做管理的模块,SecondaryNameNode是它的从节点,以防挂掉。HSFS是以master/slave模式运行的,其中NameNode、SecondaryNameNode 运行在master节点,DataNode运行slave节点。

数据块

磁盘数据块是磁盘读写的基本单位,与普通文件系统类似,hdfs也会把文件分块来存储。hdfs默认数据块大小为64MB,磁盘块一般为512B,hdfs块为何如此之大呢?块增大可以减少寻址时间与文件传输时间的比例,若寻址时间为10ms,磁盘传输速率为100MB/s,那么寻址与传输比仅为1%。当然,磁盘块太大也不好,因为一个MapReduce通常以一个块作为输入,块过大会导致整体任务数量过小,降低作业处理速度。

数据块是存储在DataNode中的,为了能够容错数据块是以多个副本的形式分布在集群中的,副本数量默认为3,后面会专门介绍数据块的复制机制。

hdfs按块存储还有如下好处:

文件可以任意大,也不用担心单个结点磁盘容量小于文件的情况
简化了文件子系统的设计,子系统只存储文件块数据,而文件元数据则交由其它系统(NameNode)管理
有利于备份和提高系统可用性,因为可以以块为单位进行备份,hdfs默认备份数量为3。
有利于负载均衡

NameNode

当一个客户端请求一个文件或者存储一个文件时,它需要先知道具体到哪个DataNode上存取,获得这些信息后,客户端再直接和这个DataNode进行交互,而这些信息的维护者就是NameNode。

NameNode管理着文件系统命名空间,它维护着文件系统树及树中的所有文件和目录。NameNode也负责维护所有这些文件或目录的打开、关闭、移动、重命名等操作。对于实际文件数据的保存与操作,都是由DataNode负责。当一个客户端请求数据时,它仅仅是从NameNode中获取文件的元信息,而具体的数据传输不需要经过NameNode,是由客户端直接与相应的DataNode进行交互。

NameNode保存元信息的种类有:

文件名目录名及它们之间的层级关系
文件目录的所有者及其权限
每个文件块的名及文件有哪些块组成

需要注意的是,NameNode元信息并不包含每个块的位置信息,这些信息会在NameNode启动时从各个DataNode获取并保存在内存中,因为这些信息会在系统启动时由数据节点重建。把块位置信息放在内存中,在读取数据时会减少查询时间,增加读取效率。NameNode也会实时通过心跳机制和DataNode进行交互,实时检查文件系统是否运行正常。不过NameNode元信息会保存各个块的名称及文件由哪些块组成。

一般来说,一条元信息记录会占用200byte内存空间。假设块大小为64MB,备份数量是3 ,那么一个1GB大小的文件将占用16*3=48个文件块。如果现在有1000个1MB大小的文件,则会占用1000*3=3000个文件块(多个文件不能放到一个块中)。我们可以发现,如果文件越小,存储同等大小文件所需要的元信息就越多,所以,Hadoop更喜欢大文件。

元信息的持久化

在NameNode中存放元信息的文件是 fsimage。在系统运行期间所有对元信息的操作都保存在内存中并被持久化到另一个文件edits中。并且edits文件和fsimage文件会被SecondaryNameNode周期性的合并

其它问题

运行NameNode会占用大量内存和I/O资源,一般NameNode不会存储用户数据或执行MapReduce任务。

为了简化系统的设计,Hadoop只有一个NameNode,这也就导致了hadoop集群的单点故障问题。因此,对NameNode节点的容错尤其重要,hadoop提供了如下两种机制来解决:

将hadoop元数据写入到本地文件系统的同时再实时同步到一个远程挂载的网络文件系统(NFS)。
运行一个secondary NameNode,它的作用是与NameNode进行交互,定期通过编辑日志文件合并命名空间镜像,当NameNode发生故障时它会通过自己合并的命名空间镜像副本来恢复。需要注意的是secondaryNameNode保存的状态总是滞后于NameNode,所以这种方式难免会导致丢失部分数据(后面会详细介绍)。

DataNode

DataNode是hdfs中的worker节点,它负责存储数据块,也负责为系统客户端提供数据块的读写服务,同时还会根据NameNode的指示来进行创建、删除、和复制等操作。此外,它还会通过心跳定期向NameNode发送所存储文件块列表信息。当对hdfs文件系统进行读写时,NameNode告知客户端每个数据驻留在哪个DataNode,客户端直接与DataNode进行通信,DataNode还会与其它DataNode通信,复制这些块以实现冗余。

NameNode和DataNode架构图

这里写图片描述

SecondaryNameNode

需要注意,SecondaryNameNode并不是NameNode的备份。我们从前面的介绍已经知道,所有HDFS文件的元信息都保存在NameNode的内存中。在NameNode启动时,它首先会加载fsimage到内存中,在系统运行期间,所有对NameNode的操作也都保存在了内存中,同时为了防止数据丢失,这些操作又会不断被持久化到本地edits文件中。

Edits文件存在的目的是为了提高系统的操作效率,NameNode在更新内存中的元信息之前都会先将操作写入edits文件。在NameNode重启的过程中,edits会和fsimage合并到一起,但是合并的过程会影响到Hadoop重启的速度,SecondaryNameNode就是为了解决这个问题而诞生的。

SecondaryNameNode的角色就是定期的合并edits和fsimage文件,我们来看一下合并的步骤:

合并之前告知NameNode把所有的操作写到新的edites文件并将其命名为edits.new。
SecondaryNameNode从NameNode请求fsimage和edits文件
SecondaryNameNode把fsimage和edits文件合并成新的fsimage文件
NameNode从SecondaryNameNode获取合并好的新的fsimage并将旧的替换掉,并把edits用第一步创建的edits.new文件替换掉
更新fstime文件中的检查点

最后再总结一下整个过程中涉及到NameNode中的相关文件

fsimage :保存的是上个检查点的HDFS的元信息
edits :保存的是从上个检查点开始发生的HDFS元信息状态改变信息
fstime:保存了最后一个检查点的时间戳

MapReduce分布式计算架构

MapReduce特点:

易于编程,用户通常情况下只需要编写Mapper和Reducer程序即可。
良好的扩展性,即可以很容易的增加节点
高容错性,一个Job默认情况下会尝试启动两次,一个mapper或者reducer默认会尝试4次,如果一个节点挂了,可以向系统申请新的节点来执行这个mapper或者reducer
适合PB级别的数据的离线处理

MapReduce框架的缺点

不擅长实时计算,像MySQL一样能够立即返回结果
MapReduce的设计本身决定了处理的数据必须是离线数据,因为涉及到数据切分等等。
不擅长DAG(有向图)计算,需要一个Job执行完成之后,另一个Job才能使用他的输出。

MapReduce编程模型:

一种分布式计算模型框架,解决海量数据的计算问题

MapReduce将整个并行计算过程抽象到两个函数
——>Map(映射):对一些独立元素组成的列表的每一个元素进行指定的操作,可以高度并行。
——>Reduce(化简):对一个列表的元素进行合并。

例如wordcount功能:

Map阶段:首先将输入数据进行分片,然后对每一片数据执行Mapper程序,计算出每个词的个数,之后对计算结果进行分组,每一组由一个Reducer程序进行处理,到此Map阶段完成。
Reduce阶段:每个Reduce程序从Map的结果中拉取自己要处理的分组(叫做Shuffling过程),进行汇总和排序(桶排序),对排序后的结果运行Reducer程序,最后所有的Reducer结果进行规约写入HDFS。

一个简单的MapReduce程序只需要指定map()、reduce()、input和output,剩下的事由架构完成。
input()——>map()——>reduce()——>output()

每个应用程序称为一个作业(Job),每个Job由一系列的Mappers和Reducers来完成。 每个Mapper处理一个分片(Split),处理过程如下:

Map阶段:

输入数据的解析:InputFormat
输入数据处理:Mapper
输入分组:Partitioner
本节点的规约:Combiner ,

Reduce阶段:

Shuffling阶段拉取数据
桶排序,是一个hash过程,使得相同的Key可以排在一堆
数据规约:Reducer
数据输出格式: OutputFormat

MapReduce2.0 架构

这里写图片描述

MapReduce2.0运行在YARN之上。YARN由ResourceManager(RM) 和NodeManager(NM)两大块组成。

MapReduce2 架构设计:
1:用户向YARN中提交应用程序,其中包括ApplicationMaster程序、启动ApplicationMaster的命令、用户程序等。
2:ResourceManager为该应用程序分配第一个Container,并与对应的Node-Manager通信,要求它在这个Container中启动应用程序的ApplicationMaster。
3:ApplicationMaster首先向ResourceManager注册,这样用户可以直接通过ResourceManage查看应用程序的运行状态,然后它将为各个任务申请资源,并监控它的运行状态,直到运行结束,即重复步骤4~7。
4:ApplicationMaster采用轮询的方式通过RPC协议向ResourceManager申请和领取资源。
5:一旦ApplicationMaster申请到资源后,便与对应的NodeManager通信,要求它启动任务。
6:NodeManager为任务设置好运行环境(包括环境变量、JAR包、二进制程序等)后,将任务启动命令写到一个脚本中,并通过运行该脚本启动任务。
7:各个任务通过某个RPC协议向ApplicationMaster汇报自己的状态和进度,以让ApplicationMaster随时掌握各个任务的运行状态,从而可以在任务失败时重新启动任务。在应用程序运行过程中,用户可随时通过RPC向ApplicationMaster查询应用程序的当前运行状态。

8:应用程序运行完成后,ApplicationMaster向ResourceManager注销并关闭自己。

MapReduce1 的架构设计:
Client: 客户端
JobTracker : 主要负责 资源监控管理和作业调度。
a.监控所有TaskTracker 与job的健康状况,一旦发现失败,就将相应的任务转移到其他节点;
b.同时JobTracker会跟踪任务的执行进度、资源使用量等信息,并将这些信息告诉任务调度器,而调度器会在资源出现空闲时,选择合适的任务使用这些资源.
TaskTracker: :是JobTracker与Task之前的桥梁
a.从JobTracker接收并执行各种命令:运行任务、提交任务、Kill任务、重新初始化任务;
b.周期性地通过心跳机制,将节点健康情况和资源使用情况、各个任务的进度和状态等汇报给JobTracker
Task Scheduler: 任务调度器(默认 FIFO,先按照作业的优先级高低,再按照到达时间的先后选择被执行的作业)
Map Task: 映射任务
Reduce Task: 归约任务

MapReduce实例——WordCount

问题:

有一批文件(规模为TB级或者PB级),如何统计这些文件中所有单词出现的次数。

方案:

首先,分别统计每个文件中单词出现的次数。

然后,累加不同文件中同一个单词出现的次数。

MapReduce WordCount实例运行

在dfs中创建input目录

root@localhost data]# hadoop fs -mkdir /wc/input

将data中的.data文件拷贝到dfs中的input

root@localhost data]# hadoop fs -put ./*.data /wc/input

查看

root@localhost data]# hadoop fs -ls /wc/input

运行wordcount

root@localhost hadoop-2.7.3]# hadoop jar hadoop-examples-1.2.1.jar wordcount /wc/input /wc/output

MapReduce基本流程

首先,将数据输入到HDFS,再交给map,map对每个单词进行统计

在map之后reduce之前进行排序

然后,将排好序的数据拷贝并进行合并,合并好的数据交给reduce,reduce再将完成的数据输出回HDFS

这里写图片描述
这里写图片描述

MapReduce执行流程

Map任务处理

1,读取输入文件内容,解析成key、value对。对输入文件的每一行,解析成key、value对。每一个键值对调用一次map函数。

2,写自己的逻辑,对输入的key、value处理,转换成新的key、value输出。

3,对输出的key、value进行分区

4、对不同分区的数据,按照key进行排序、分组。相同key的value放到一个集合中。

5、(可选)分组后的数据进行归约。

Reduce任务处理

1,对多个map任务的输出,按照不同的分区,通过网络copy到不同的reduce节点。

2,对多个map任务的输出进行合并、排序。写reduce函数自己的逻辑,对输入的key、value处理,转换成新的key、value输出。

3、把reduce的输出保存到文件中。

编写MapReduce程序

基于MapReduce计算模型编写分布式并行程序非常简单,程序员的主要编码工作就是实现map和reduce函数。

MapReduce中,map和reduce函数遵循如下常规格式:

map:(K1,V1)——>list(K2,V2)
reduce:(K2,list(V2)) ——>list(K3,V3)

Mapper的接口:

protected void reduce(KEY key,Iterable<VALUE>values,Context context) throws IOException,interruptedException {

}

Reduce的接口:

protected void reduce(KEY key,Iterable<VALUE>values,Context context) throws IOException,interruptedException {

}

Spark相对于MapReduce的优势

MapReduce存在的问题

  1. MapReduce框架局限性

      1)仅支持Map和Reduce两种操作

      2)处理效率低效。

        a)Map中间结果写磁盘,Reduce写HDFS,多个MR之间通过HDFS交换数据; 任务调度和启动开销大;

        b)无法充分利用内存

        c)Map端和Reduce端均需要排序

      3)不适合迭代计算(如机器学习、图计算等),交互式处理(数据挖掘) 和流式处理(点击日志分析)

  2. MapReduce编程不够灵活

      1)尝试scala函数式编程语言

Spark

  1. 高效(比MapReduce快10~100倍)

      1)内存计算引擎,提供Cache机制来支持需要反复迭代计算或者多次数据共享,减少数据读取的IO开销

      2)DAG引擎,减少多次计算之间中间结果写到HDFS的开销

      3)使用多线程池模型来减少task启动开稍,shuffle过程中避免 不必要的sort操作以及减少磁盘IO操作

  2. 易用

      1)提供了丰富的API,支持Java,Scala,Python和R四种语言

      2)代码量比MapReduce少2~5倍

  3. 与Hadoop集成 读写HDFS/Hbase 与YARN集成

spark应用执行机制分析

目前Apache Spark支持三种分布式部署方式,分别是standalone、spark on mesos和 spark on YARN,其中,第一种类似于MapReduce 1.0所采用的模式,内部实现了容错性和资源管理,后两种则是未来发展的趋势,部分容错性和资源管理交由统一的资源管理系统完成:让Spark运行在一个通用的资源管理系统之上,这样可以与其他计算框架,比如MapReduce,公用一个集群资源,最大的好处是降低运维成本和提高资源利用率(资源按需分配)。本文将介绍这三种部署方式,并比较其优缺点。

1. Standalone模式

  即独立模式,自带完整的服务,可单独部署到一个集群中,无需依赖任何其他资源管理系统。从一定程度上说,该模式是其他两种的基础。借鉴Spark开发模式,我们可以得到一种开发新型计算框架的一般思路:先设计出它的standalone模式,为了快速开发,起初不需要考虑服务(比如master/slave)的容错性,之后再开发相应的wrapper,将stanlone模式下的服务原封不动的部署到资源管理系统yarn或者mesos上,由资源管理系统负责服务本身的容错。目前Spark在standalone模式下是没有任何单点故障问题的,这是借助zookeeper实现的,思想类似于Hbase master单点故障解决方案。将Spark standalone与MapReduce比较,会发现它们两个在架构上是完全一致的: 

  1) 都是由master/slaves服务组成的,且起初master均存在单点故障,后来均通过zookeeper解决(Apache MRv1的JobTracker仍存在单点问题,但CDH版本得到了解决);
  2) 各个节点上的资源被抽象成粗粒度的slot,有多少slot就能同时运行多少task。不同的是,MapReduce将slot分为map slot和reduce slot,它们分别只能供Map Task和Reduce Task使用,而不能共享,这是MapReduce资源利率低效的原因之一,而Spark则更优化一些,它不区分slot类型,只有一种slot,可以供各种类型的Task使用,这种方式可以提高资源利用率,但是不够灵活,不能为不同类型的Task定制slot资源。总之,这两种方式各有优缺点。

流程:
1、使用SparkSubmit提交任务的时候(包括Eclipse或者其它开发工具使用new SparkConf()来运行任务的时候),Driver运行在Client;使用SparkShell提交的任务的时候,Driver是运行在Master上
2、使用SparkSubmit提交任务的时候,使用本地的Client类的main函数来创建sparkcontext并初始化它;
3、SparkContext连接到Master,注册并申请资源(内核和内存)。
4、Master根据SC提出的申请,根据worker的心跳报告,来决定到底在那个worker上启动StandaloneExecutorBackend(executor)
5、executor向SC注册
6、SC将应用分配给executor,
7、SC解析应用,创建DAG图,提交给DAGScheduler进行分解成stage(当出发action操作的时候,就会产生job,每个job中包含一个或者多个stage,stage一般在获取外部数据或者shuffle之前产生)。然后stage(又称为Task Set)被发送到TaskScheduler。TaskScheduler负责将stage中的task分配到相应的worker上,并由executor来执行
8、executor创建Executor线程池,开始执行task,并向SC汇报
9、所有的task执行完成之后,SC向Master注销
这里写图片描述

2. Spark On Mesos模式

这是很多公司采用的模式,官方推荐这种模式(当然,原因之一是血缘关系)。正是由于Spark开发之初就考虑到支持Mesos,因此,目前而言,Spark运行在Mesos上会比运行在YARN上更加灵活,更加自然。目前在Spark On Mesos环境中,用户可选择两种调度模式之一运行自己的应用程序(可参考Andrew Xia的“Mesos Scheduling Mode on Spark”):

  1) 粗粒度模式(Coarse-grained Mode):每个应用程序的运行环境由一个Dirver和若干个Executor组成,其中,每个Executor占用若干资源,内部可运行多个Task(对应多少个“slot”)。应用程序的各个任务正式运行之前,需要将运行环境中的资源全部申请好,且运行过程中要一直占用这些资源,即使不用,最后程序运行结束后,回收这些资源。举个例子,比如你提交应用程序时,指定使用5个executor运行你的应用程序,每个executor占用5GB内存和5个CPU,每个executor内部设置了5个slot,则Mesos需要先为executor分配资源并启动它们,之后开始调度任务。另外,在程序运行过程中,mesos的master和slave并不知道executor内部各个task的运行情况,executor直接将任务状态通过内部的通信机制汇报给Driver,从一定程度上可以认为,每个应用程序利用mesos搭建了一个虚拟集群自己使用。

  2) 细粒度模式(Fine-grained Mode):鉴于粗粒度模式会造成大量资源浪费,Spark On Mesos还提供了另外一种调度模式:细粒度模式,这种模式类似于现在的云计算,思想是按需分配。与粗粒度模式一样,应用程序启动时,先会启动executor,但每个executor占用资源仅仅是自己运行所需的资源,不需要考虑将来要运行的任务,之后,mesos会为每个executor动态分配资源,每分配一些,便可以运行一个新任务,单个Task运行完之后可以马上释放对应的资源。每个Task会汇报状态给Mesos slave和Mesos Master,便于更加细粒度管理和容错,这种调度模式类似于MapReduce调度模式,每个Task完全独立,优点是便于资源控制和隔离,但缺点也很明显,短作业运行延迟大。

3. Spark On YARN模式

这是一种很有前景的部署模式。但限于YARN自身的发展,目前仅支持粗粒度模式(Coarse-grained Mode)。这是由于YARN上的Container资源是不可以动态伸缩的,一旦Container启动之后,可使用的资源不能再发生变化,不过这个已经在YARN计划中了。

  spark on yarn 的支持两种模式:
    1) yarn-cluster:适用于生产环境;
    2) yarn-client:适用于交互、调试,希望立即看到app的输出

  yarn-cluster和yarn-client的区别在于yarn ApplicationMaster,每个yarn app实例有一个ApplicationMaster进程,是为app启动的第一个container;负责从ResourceManager请求资源,获取到资源后,告诉NodeManager为其启动container。yarn-cluster和yarn-client模式内部实现还是有很大的区别。如果你需要用于生产环境,那么请选择yarn-cluster;而如果你仅仅是Debug程序,可以选择yarn-client。

Spark运行模式列表(一定要熟悉!)

这里写图片描述

注意: Spark on Yarn 有 yarn client 和 yarn clusters 模式。

    Spark on Standalone 也有 standalone client 和 standalone clusters 模式。

yarn client流程

1、spark-submit脚本提交,Driver在客户端本地运行;
2、Client向RM申请启动AM,同时在SC(client上)中创建DAGScheduler和TaskScheduler。
3、RM收到请求之后,查询NM并选择其中一个,分配container,并在container中开启AM
4、client中的SC初始化完成之后,与AM进行通信,向RM注册,根据任务信息向RM申请资源
5、AM申请到资源之后,与AM进行通信,要求在它申请的container中开启CoarseGrainedExecutorBackend(executor)。Executor在启动之后会向SC注册并申请task
6、SC分配task给executor,executor执行任务并向Driver(运行在client之上的)汇报,以便客户端可以随时监控任务的运行状态
7、任务运行完成之后,client的SC向RM注销自己并关闭自己
这里写图片描述

yarn cluster流程

1、spark-submit脚本提交,向yarn(RM)中提交ApplicationMaster程序、AM启动的命令和需要在Executor中运行的程序等
2、RM收到请求之后,选择一个NM,在其上开启一个container,在container中开启AM,并在AM中完成SC的初始化
3、SC向RM注册并请求资源,这样用户可以在RM中查看任务的运行情况。RM根据请求采用轮询的方式和RPC协议向各个NM申请资源并监控任务的运行状况直到结束
4、AM申请到资源之后,与对应的NM进行通信,要求在其上获取到的Container中开启CoarseGrainedExecutorBackend(executor),executor 开启之后,向AM中的SC注册并申请task
5、AM中的SC分配task给executor,executor运行task兵向AM中的SC汇报自己的状态和进度
6、应用程序完成之后(各个task都完成之后),AM向RM申请注销自己兵关闭自己
这里写图片描述

阅读更多
版权声明:本文为博主原创文章,转载请注明来源。开发合作联系luanpenguestc@sina.com https://blog.csdn.net/luanpeng825485697/article/details/80319552
文章标签: hadoop hbase hive spark
个人分类: 架构
所属专栏: web服务器架构
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

不良信息举报

hadoop、hbase、hive、spark分布式系统架构原理

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭