Hadoop大数据实战权威指南(第2版)
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

2.4 分布式计算框架

随着各种硬件设备和网络性能的快速发展,人们可以更快地获得原始的海量数据。虽然有很多专用的算法可以处理这些数据,但是,由于输入的数据量巨大,在只有一台主机参与计算的情况下,很难在可接受的时间范围内得到结果。如果有成千上万台的主机参与计算,每台主机只处理其中一小部分数据,就会很容易在可接受的时间范围内得到结果。但是当成千上万台的主机出现的时候,如何处理并行计算、如何分发数据、如何处理错误、这些都是分布式计算框架要解决的问题。

2.4.1 离线计算框架

1. MapReduce

MapReduce是出现最早、知名度最大的分布式计算框架,主要用于大批量的集群任务。MapReduce致力于解决大规模数据处理的问题,在设计之初就考虑了数据的局部性原理。MapReduce利用局部性原理将整个问题分而治之。MapReduce指的是Map(映射)和Reduce(归约)两种函数,也是计算过程的两个阶段。Map函数对类型为Key-Value的数据进行映射处理,之后交给Reduce函数进行归约处理。简单地说,MapReduce就是将一个规模比较大的任务拆分成多个规模比较小的任务同时并行进行作业,在完成各个规模比较小的任务后,再将它们进行归约聚合,这也是并行分布式计算思想的体现。当一个任务失败时,调度器会挑选另一个节点重新开始作业,从而保证系统的可靠性、容错性。利用该模型,使用者只需关注想要执行的运算逻辑规则,而不必关心分布式执行中的容错、数据和计算分布、负载均衡等复杂的细节,MapReduce框架会自动处理这些问题。图2-12给出了MapReduce的执行流程。

图2-12 MapReduce的执行流程

由于Hadoop相比传统计算模式的突出优势,基于Hadoop的应用已经被大量开发,尤其是在互联网领域,Hadoop目前足以承担PB级的大数据处理任务,MapReduce也已经成为主流的分布式编程模型。

MapReduce集群由普通PC构成,是无共享式的架构。在处理之前,将数据集分布至各个节点。在处理时,每个节点就近读取本地存储的数据处理(Map),并对处理后的数据进行合并(Combine)、排序(Shuffle和Sort)后再进行分发(至Reduce节点),避免了大量数据的传输,提高了处理效率。无共享式架构的另一个好处是配合复制(Replication)策略,MapReduce集群可以具有良好的容错性,一部分节点的宕机不会对集群的正常工作造成影响。基于MapReduce的应用程序能够运行在由上千个商用机器组成的大型集群上,并以一种可靠容错的方式并行处理上TB级的数据集。

MapReduce适合PB级以上的海量数据离线处理。文件是MapReduce任务的数据初始存储地。输入文件一般存在HDFS中,这些文件的格式可以是任意的,可以是基于行的日志文件,也可以使用二进制格式、多行输入记录或其他一些格式。这些文件会很大,通常为数十吉字节或更大。这种设计原理决定了其数据是静态的,不能动态变化,因此,MapReduce不能处理流式计算,而且由于是批量执行的,因此时效性偏低。

MapReduce的优点是灵活性很高,它不仅可以部署到Hadoop框架中,而且可以部署到多种分布式框架中。现在,云计算技术已逐渐成熟,Hadoop可以轻松地部署在云上,并且不会增加开销。

MapReduce第一个版本(MRv1)的主要不足表现在大型集群上。当集群包含的节点超过4000个时(其中每个节点可能是多核的),就会表现出一定的不可预测性,其中一个最大的问题是级联故障,由于要尝试复制数据和重载活动的节点,所以一个故障会通过网络泛洪形式导致整个集群崩溃。总体说来,MRv1存在扩展性受限、单点故障、难以支持MR之外的计算等缺陷,多个计算框架各自为战,数据共享困难。针对这些问题,Yarn(MRv2)应运而生了。

2. Yarn(MRv2)

Hadoop的发展并没有因为MRv1的不足而停止。从MapReduce 0.23.0版本开始,Hadoop开发团队摒弃了原有框架,从根本上进行了改变。新的MapReduce框架命名为Yarn或MRv2。

MRv1的JobTracker和TaskTracker方法是一个重要的缺陷,它关系到可伸缩性、资源利用,以及对MapReduce不同的工作负载的支持。在MapReduce框架中,作业执行受两种类型的进程控制:一个是称为JobTracker的主要进程,用于协调在集群上运行的所有作业,分配要在TaskTracker上运行的Map和Reduce任务;另一个是称为TaskTracker的下级进程,用于运行分配的任务,并定期向JobTracker报告进度。

大型的Hadoop集群出现了由单个JobTracker导致的可伸缩性瓶颈。例如,当在集群中有5000个节点和40000个任务同时运行时,这样一种设计实际上就会受到限制。由于此限制,因此不得不创建和维护更小的、功能更差的集群。此外,较小和较大的Hadoop集群都从未最高效地使用它们的计算资源。在MapReduce中,每个从属节点上的计算资源由集群管理员分解为固定数量的Map Slot和Reduce Slot,这些Slot不可替代。设定Map Slot和Reduce Slot的数量后,节点在任何时刻都不能运行比Map Slot更多的Map任务,即使没有Reduce任务在运行。这影响了集群的利用率,因为在所有Map Slot都被使用(而且还需要更多)时,无法使用任何Reduce Slot,即使它们可用;反之亦然。

在MapReduce中,JobTracker具有两种不同的职责:

(1)管理MapReduce集群中的计算资源,这涉及维护活动节点列表、可用或占用的Map Slot和Reduce Slot列表,以及依据所选的调度策略将可用的Slot分配给合适的作业和任务。

(2)协调在MapReduce集群上运行的所有任务,这涉及指导TaskTracker启动Map Reduce任务、监视任务的执行、重新启动失败的任务、推测性地运行缓慢的任务、计算作业计数器值的总和等。为单个进程安排大量职责会导致重大的可伸缩性问题,尤其是在较大的集群上。

为了解决可伸缩性问题,一个简单而又绝妙的想法是减少单个JobTracker的职责,将部分职责交给TaskTracker,因为MapReduce集群中有许多TaskTracker。在新的设计中,这个概念通过将JobTracker的双重职责(集群资源管理和任务协调)分为两种不同类型的进程来实现。

Yarn不再拥有单个JobTracker,而是引入了一个集群管理器,它唯一的职责就是跟踪MapReduce集群中的活动节点和可用资源,并为它们分配任务。对于提交给MapReduce集群的每个作业,会启动一个专用的、短暂的JobTracker来控制该作业中任务的执行。短暂的JobTracker由在从属节点上运行的TaskTracker启动。因此,作业的生命周期的协调工作就分散到了MapReduce集群中所有可用的机器上。得益于这种设计,更多工作可并行完成,可伸缩性得到了显著提高。

为了实现上述设计,在Yarn中,将MRv1中JobTracker的资源管理和任务调度、监控分离。在Yarn框架中增加了一个Resource Manager来全局管理所有应用程序计算资源的分配,同时,每个节点中增加了一个Node Manger,它是节点的代理。

Yarn在处理日志方面也做了较大的改进,现在的Node Manager会将日志进行压缩后再传送到文件系统中。

可以看出,MRv1受到了JobTracker的约束,JobTracker负责整个集群的资源管理和作业调度。Yarn打破了这种模型,引用了Resource Manager来管理跨应用程序的资源使用,Application Master负责管理作业的执行。这一更改不仅消除了MRv1的瓶颈,还改善了Hadoop集群的扩展能力。此外,不同于MRv1,Yarn允许使用消息传递接口(Message Passing Interface,MPI)等标准通信模式,同时可执行不同的编程模型,包括图形处理、迭代式处理、机器学习和一般集群计算等。

随着Yarn的出现,Hadoop将不再受MRv1开发模式的约束,可以创建更复杂的分布式应用程序。实际上,可以将MapReduce MRv1视为Yarn架构可运行应用程序的一部分。Yarn几乎没有限制,不再需要与一个集群上可能存在的其他更复杂的分布式应用程序框架相隔离。随着Yarn变得更加健全,它有能力取代其他一些分布式处理框架,同时还可以简化整个系统。

3. Spark

随着Yarn的出现,MapReduce的使用者不需要担心任务的并行性和容错问题,只需要使用一些基本的操作就能并行地读写数据。但是,由于MapReduce框架并没有很好地使用分布式内存,每个MapReduce任务均需要读写磁盘,这使得MapReduce对于某些需要重用中间结果的应用效率很低。在很多迭代式的机器学习和数据挖掘算法中,使用中间结果是非常常见的。如果使用MapReduce框架来处理这类应用,那么数据副本、磁盘I/O和数据序列化将会花费大量时间。因为内存的读写速度远远高于磁盘。在理想状况下,如果所有的工作数据都能放入内存,那么大部分的任务就能在很短的时间内完成。

为了避免MapReduce框架中多次读写磁盘的消耗,更充分地利用内存,加州大学伯克利分校AMP Lab提出了一种新的、开源的、类似于MapReduce的内存编程模型—Spark。Spark是基于MapReduce算法实现分布式计算的,拥有MapReduce的优点;不同于MapReduce的是Job Tracker中间输出和结果可以保存在内存中,从而不再需要读写HDFS,因此Spark能更好地适用于数据挖掘与机器学习等场景。Spark掀起了内存计算之先河,引领了大数据技术的发展。

Spark是基于内存的分布式计算框架。在迭代计算的场景下,数据处理过程中的数据都会存储在内存中,从而避免了MapReduce计算框架中的问题。Spark能够使用HDFS,使用户能够快速地从MapReduce切换到Spark,并且提供比MapReduce高10~100倍的性能。作为计算引擎,Spark还支持小批量流式处理、离线批处理、SQL查询、数据挖掘,避免用户在这几类不同的系统中加载同一份数据带来的存储和性能上的开销。Spark能够融入Hadoop的生态系统。

Spark是用Scala语言编写而成的,Scala是一种运行在Java虚拟机上的高级静态语言,是一种函数式编程语言。Spark支持多语言编程,主要支持Scala、Java、Python、R四种语言,这一特点使得开发者可以使用自己熟悉的语言进行开发。Spark自带了80多个内置API,如map、flatMap、groupBy、filter等,这些API使得Spark的易用性更强,同时允许在脚本(Shell)中进行交互式计算。

目前,Spark正在促使Hadoop的大数据生态系统发生演变,以便更好地支持大数据的分析需求。Spark已经在其核心的基础上发展了Spark Streaming、Spark SQL、MLlib、GraphX等组件,使其在支持传统批处理应用的同时,能够支持交互式查询、流计算、机器学习、图计算等各种应用,满足各种场景的需求。这些应用都是基于Spark框架的,可以简单地把以上各种应用整合到一起,在实际应用中具有重要的意义。

Spark也已经结合Hadoop等大数据处理工具发展出了自己的生态系统。Spark的生态系统如图2-13所示,读者可以参考相关文献了解其中涉及的组件,本书将在后面的章节中重点介绍Spark MLlib的应用。

图2-13 Spark的生态系统

由于Spark是基于内存的迭代计算框架,因此非常适用于需要多次操作特定数据集的场景。需要反复操作的次数越多,所需读取的数据量越大,受益就越大,数据量小但是计算密集度较大的场景,受益就相对较小。由于RDD的特性,Spark不适合那种异步小粒度更新状态的应用,例如,Web服务的存储或者增量的Web爬虫和索引,对于那种增量修改的应用模型不适合。

在学术界,Spark早已得到各大院校的关注。Spark源于加州大学伯克利分校,目前国内一些知名大学也都开始对其展开相关的研究。而在工业界,Spark已经在互联网领域得到了广泛的应用。例如,国外Cloudera、MapR等大数据厂商全面支持Spark框架,Amazon和Yahoo都在使用Spark进行日志分析。在国内,淘宝使用Spark进行用户交易数据分析,网易在使用Spark对海量数据进行报表查询,腾讯使用Spark进行精准广告推荐等,豆瓣也在使用Spark的Python克隆版DPark。可见Spark的优势之大与流行之广。

4. Flink

Flink是一个高效、分布式、基于Java实现的通用大数据分析引擎,它具有类似于MapReduce的高效性、灵活性和扩展性,以及并行数据库查询优化方案,支持批量和基于流式数据的分析,且提供了基于Java和Scala的API。Flink已升级成为Apache基金会的顶级项目,其设计思想主要来源于Hadoop、MPP数据库、流式计算系统等,支持增量迭代计算。

对于Flink而言,其所要处理的主要场景就是流数据,批数据只是流数据的一个特例。换句话说,Flink会把所有任务当成流来处理,这也是其最大的特点,Flink可以支持毫秒级流式计算。

Flink有几个最基础的概念,如Client、JobManager和TaskManager。Client用来提交任务给JobManager,JobManager分发任务给TaskManager去执行,TaskManager会通过心跳消息来汇报任务状态。看到这里,有的人应该已经有种回到了Hadoop的错觉。确实,从架构来看,JobManager很像JobTracker,TaskManager也很像TaskTracker。然而有一个最重要的区别就是,TaskManager之间是流(Stream)。在Hadoop中,只有Map和Reduce之间的Shuffle,而对Flink而言,可能是很多级,并且在TaskManager内部和TaskManager之间都会有数据传递,而不像在Hadoop中那样在固定的Map到Reduce之间传递数据。

Flink具有如下主要特征:

  • 数据集DataSet的API支持Java、Scala和Python等语言;
  • 数据流DataStream的API支持Java和Scala等语言;
  • 表(Table)的API支持类似于SQL的查询;
  • 具有机器学习和图处理(Gelly)的各种库;
  • 具有自动优化迭代的功能,如有增量迭代;
  • 支持高效序列化和反序列化。

Flink与Hadoop兼容性很好,Flink支持Hadoop所有的输入/输出格式和数据类型,这使得开发者无须做任何修改就能够利用Flink运行MapReduce任务。

Flink具有快速的特点,Flink利用基于内存的数据流并将迭代处理算法深度集成到了系统的运行时中,这使得系统能够以极快的速度来处理数据密集型任务和迭代任务。

Flink可靠性和扩展性很高。当服务器的内存被耗尽时,Flink也能够很好地运行,这是因为Flink包含自己的内存管理组件、序列化框架和类型推理引擎。

Flink的易用性也很好。在无须进行任何配置的情况下,Flink内置的优化器就能够以最高效的方式在各种环境中执行程序。Flink只需要三个命令就可以运行在Yarn上。图2-14给出了Flink on Yarn的运行机制。

Spark和Flink都支持实时计算,且都可基于内存进行计算。Flink对流式计算和迭代计算的支持力度更强。无论Spark还是Flink,它们的发展重点都是将数据和平台API化,除了传统的统计算法,还包括学习算法,同时使其生态系统越来越完善。

图2-14 Flink on Yarn的运行机制

2.4.2 实时流计算平台

随着互联网应用的高速发展,企业积累的数据量越来越多。随着Hadoop、MapReduce等相关技术的出现,处理大规模数据变得简单起来,但是这些数据处理技术都不是实时的系统,它们的设计目标也不是实时计算。实时的计算系统和基于批处理模型的系统(如Hadoop系统)有着本质的区别。

随着大数据业务的快速增长,针对大规模数据处理的实时计算变成了一种业务上的需求。例如,银行的实时营销和实时风险预警场景需要大数据平台具有历史数据快速统计、窗口时间内的信息流、触发事件及模型匹配、百毫秒级事件响应等性能。缺少实时的Hadoop系统已经成为整个大数据生态系统中的一个巨大瓶颈,Storm正是在这样的需求背景下出现的。

在Storm出现之前,对于需要实现计算的任务,开发者需要手动维护一个消息队列和消息处理者所组成的实时处理网络。消息处理者先从消息队列中获取消息后进行处理,然后更新数据库,发送消息给其他队列,所有这些操作都需要开发者自己实现。

目前Hadoop平台通用的流处理引擎主要为Spark Streaming和Storm,两者各有千秋。Spark Streaming由时间窗口内批量事件流触发,Storm由单个事件触发;在单笔交易延迟方面,Spark Streaming优于Storm,但在整体吞吐量方面Spark Streaming略有提升。在进行Hadoop选型时主要考虑处理引擎是否能够在流上实现统计类挖掘算法。

下面主要介绍实时编程模型Storm和Spark Streaming。

1. Storm

Storm是Twitter的一个类似于Hadoop的开源实时数据处理框架(原来是由BackType开发的,后BackType被Twitter收购,将Storm作为Twitter的实时数据分析系统)。Storm能处理高频交易数据和大规模数据的实时流计算,可应用于实时搜索、高频交易和社交网络等。金融机构的交易系统是一个非常典型的流计算处理系统,对实时性和一致性有很高的要求。

(1)Storm的设计思想。在Storm中也有对于流(Stream)的抽象。Storm将流中元素抽象为Tuple(元组),一个Tuple就是一个值列表(Value List),值列表中的每个Value都有一个Name,并且该Value可以是基本类型、字符类型、字节数组等,当然也可以是其他可序列化的类型。Storm流如图2-15所示。

图2-15 Storm流

本质上讲,流是一个不间断的、无界的连续Tuple。在建模事件流时,Storm把流中的事件抽象为Tuple,即元组。Storm认为每个流(Stream)都有一个源,也就是Tuple的源头,所以它将这个源头抽象为Spout,Spout可能是连接Twitter的API并不断发出Tweet(Twitter发出的帖子),也可能是从某个队列中不断读取队列元素并装配为Tuple后再发送出来。

有了源头,即Spout,也就有了Stream,那么该如何处理Stream内的Tuple呢?同样,Twitter将Stream的中间状态转换抽象为Bolt。Bolt可以消费任意数量的输入流,只要将流的方向导向该Bolt,同时也可以发送新的流给其他Bolt使用,这样一来,只要打开特定的Spout(管口)再将Spout中流出的Tuple导向特定的Bolt,由Bolt对导入的流做处理后再导向其他Bolt或者目的地。

形象地说,Spout就好像是一个个水龙头,并且每个水龙头里流出的水是不同的,我们想用哪种水就拧开哪个水龙头,然后使用管道将水龙头中的水导向到一个处理器(Bolt),经Bolt处理后再使用管道导向另一个处理器或者存入容器中。Spout流的概念如图2-16所示。

图2-16 Spout流的概念

为了增大水处理效率,很自然地就想到了在同一个水源处接上多个水龙头并使用多个处理器,这样就可以提高效率。

Storm对数据输入的来源和数据输出的去向没有做任何限制,在Storm中,可以使用任意来源的数据输入和任意的数据输出,只要编写对应的代码来获取/写入这些数据即可。在典型的场景下,数据输入的来源和数据输出的去向是类似于Kafka或者ActiveMQ这样的消息队列,也可以是数据库、文件系统或者Web服务。

图2-17是Storm的拓扑。拓扑是Storm最高层次的一个抽象概念,它可以被提交到Storm集群执行,一个拓扑就是一个流转换图,图中每个节点都是一个Spout或者Bolt,图中的边表示Bolt订阅了哪些流,当Spout或者Bolt发送元组到流时,Spout就会发送元组到每个订阅了该流的Bolt(只要预先订阅,Spout就会将流发到适当的Bolt上)。

图2-17 Storm的拓扑

为了进行实时计算,用户需要设计一个拓扑图,并实现其中Bolt的处理细节,Storm拓扑定义的仅仅是一些Thrift结构体,这样一来我们就可以使用其他语言来创建和提交拓扑。

拓扑的每个节点都要说明它所发送的元组字段的Name,其他节点只需要订阅该Name即可。

Storm对数据的处理效率很高,而且支持水平扩展,具有高容错性。Storm将流上的查询抽象为一个拓扑结构,该拓扑结构是一个由多个算子组成的有向无环图,主要包括消息发送者和消息处理者两类算子。消息发送者既可以通过编程来自行生成数据,也可以接收外界的数据;数据处理者既可以对接收到的数据进行处理,也可以单纯地作为一个数据的传递者。数据在拓扑结构中被抽象成一个个的数据元组,流则被抽象成一组数据元组序列。

(2)Storm的特点。Storm针对大数据应用提供了一些原语供开发者使用,这为开发者的应用设计带来了很大的便利。

可扩展性:Storm集群中的处理逻辑由任务来实现,计算任务可以在多个线程、进程和服务器之间并行进行,其并行程度由开发者事先设定,支持灵活的水平扩展。

高可靠性:Storm的高可靠性表现在保证由消息发送者发出的每条消息都能被完全处理,这也是Storm区别于其他实时系统的地方。当消息由消息发者发送出去时,系统会启动一个后台进程监控这个消息,并向消息发送者发送反馈。可以把消息经过各个节点的过程抽象成一棵消息树,如果某一个消息未被正常处理或者在规定的时间阈值之内未被处理,则监控进程就会通知消息发送者重新发送该消息,直到这棵消息树中的消息都被完全处理了之后,消息发送者才会认为消息被安全处理。

高容错性:Storm保证一个处理单元永远运行,除非使用者显式地杀死这个处理单元。当一个处理单元出现运行故障时,Storm会重新布置这个处理单元,不过,Storm不负责保存各个处理单元的中间状态信息。如果某个处理单元中存储了中间状态,那么需要由开发者自行设计相关功能模块,以保障它在被重新启动时能够恢复故障前的状态。

支持多种编程语言:Storm采用一项多语言协议来支持多种编程语言。

(3)Storm的应用。与Hadoop不同,Storm是没有包括任何存储概念的计算系统,这可以让Storm应用在多种不同的场景下。

Storm的应用范围很广,如实时分析、在线机器学习(Online Machine Learning)、连续计算(Continuous Computation)、分布式远程过程调用(RPC)、ETL等;Storm的处理速度也很快,每个节点每秒可以处理超过百万的数据组;Storm具有高扩展(Scalable)性和高容错(Fault-Tolerant)性,保证数据会被处理,而且很容易搭建和操作。

Twitter产生趋势信息是Storm的一个典型应用。Twitter可以从海量帖子中抽取趋势信息,并在本地区域和国家层级进行维护。这意味着一旦一个案例开始出现,Twitter的话题趋势算法就能实时地鉴别出这个话题。这个算法就是通过在Storm上连续分析Twitter的帖子来实现的。

Storm被广泛用来进行实时日志处理,如应用于实时统计、实时风控、实时推荐等场景中。淘宝用它对超大量的日志进行统计,从中提取有用的信息。日志以持久的消息队列的形式被读到Spout,然后在拓扑中计算处理得到结果,最终结果被保存在数据库中供使用。淘宝同时使用Storm和消息队列,每天能够处理200万到15亿条日志,日志量可达到2 TB,这对实时处理大数据和持续存储都有很高的要求。

2. Spark Streaming

Spark Streaming是大规模流式计算并行处理框架,它将流式计算分解成一系列短小的批处理作业。Spark Streaming是在2013年被添加到Spark中的,它可以实时处理来自Kafka、Flume和Amazon Kinesis等多种数据。Spark Streaming提供了一套高效、可容错的准实时大规模流式计算并行处理框架,它能和批处理、即时查询放在同一个软件栈中,这种对不同数据的统一处理能力正是Spark Streaming被迅速采用的关键原因之一。Spark Streaming的用户包括Uber、Netflix和Pinterest等公司。

(1)Spark Streaming框架。Spark Streaming将流式计算分解成一系列短小的批处理作业,这里的批处理引擎是Spark,也就是把Spark Streaming的输入数据按照Batch Size分成一段一段的数据,即离散流(Discretized Stream,DStream),每一段DStream都转换成Spark中的弹性分布式数据集(Resilient Distributed Dataset,RDD),然后将Spark Streaming中对DStream的Transformation操作变为针对Spark中对RDD的Transformation操作,将RDD经过操作变成中间结果保存在内存中。整个流式计算可以根据业务的需求对中间的结果进行迭加,或者存储到外部设备中。图2-18显示了Spark Streaming流程。

(2)Spark Streaming的应用。

① 网站流量统计。在互联网应用中,网站流量统计是一种常用的应用模式,需要在不同粒度上对不同数据进行统计,既有实时性的需求,又需要涉及聚合、去重、连接等较为复杂的统计需求。若使用MapReduce框架,虽然可以很容易地实现较为复杂的统计需求,但实时性却无法得到保证;反之,若采用Storm框架,虽然实时性虽然可以得到保证,但需求的实现复杂度也大大提高了。Spark Streaming在两者之间找到了一个平衡点,能够以准实时的方式容易地满足较为复杂的统计需求。

图2-18 Spark Streaming流程

② 数据暂存。Kafka作为分布式消息队列,既有非常优秀的吞吐量,又有较高的可靠性和扩展性。采用Kafka作为日志传递中间件来接收日志,既可以抓取客户端发送的流量日志,又可以接收Spark Streaming的请求,将流量日志按序发送给Spark Streaming集群。

③ 数据处理。将Spark Streaming集群与Kafka集群对接,Spark Streaming集群将从Kafka集群中获取流量日志并进行处理。Spark Streaming集群会实时地从Kafka集群中获取数据并将其存储在内部的可用内存空间中。当每一个批处理(Batch)窗口到来时,便可对这些数据进行处理。

④ 结果存储。为了便于前端展示和页面请求,处理得到的结果将被写入数据库中。

相比于传统的处理框架,Kafka+Spark Streaming的框构具有以下几个优点。

  • Spark Streaming框架的高效和低延迟保证了操作的准实时性。
  • 利用Spark Streaming框架提供的丰富API和高灵活性,可以简捷地实现较为复杂的算法。
  • 编程模型的高度一致使得上手Spark Streaming相当容易,同时也可以保证业务逻辑在实时处理和批处理上的复用。

在基于Kafka+Spark Streaming的流量统计应用运行过程中,有时会遇到内存不足、垃圾回收(GC)阻塞等各种问题。下面介绍一下如何对Spark Streaming应用程序进行调优来减少甚至避免这些问题的影响。

⑤ 从Uber到Pinterest。虽然不同的目标和业务使用Spark Streaming的方式不同,但其主要场景包括流ETL(在数据进入存储系统之前对其进行清洗和聚合)、触发器(实时检测异常行为并触发相关的处理逻辑)、数据浓缩(将实时数据与静态数据浓缩成更为精练的数据以便进行实时分析)、复杂会话和持续学习(将与实时会话相关的事件,如用户登录Web网站或者执行应用程序之后的行为组合起来进行分析)。

例如,Uber通过Kafka、Spark Streaming和HDFS构建了持续性的ETL管道,该管道首先对每天从移动用户那里收集到的TB级事件数据进行转换,将原始的非结构化事件数据转换成结构化数据,然后进行实时遥测分析。Pinterest的ETL数据管道始于Kafka,通过Spark Streaming将数据存入Spark中后实时分析全球用户对Pin的使用情况,从而优化推荐引擎为用户显示更相关的Pin。Netflix也是通过Kafka和Spark Streaming构建推荐引擎的,对每天从各种数据源接收到的数十亿事件进行分析后进行推荐。

(3)Spark Streaming与Storm的比较。Storm和Spark Streaming在处理领域上有一定的差异,Storm比较擅长实时性较高的数据处理,而Spark streaming则擅长内存处理(注意,严格来说,内存处理跟流式处理并不是完全一样的)。

在数据安全性方面,Storm的功能虽然没有Spark Streaming强大,但从目前来看已经够用了,要知道很多业务数据在这种场合下是允许丢失部分数据的。相对来说,在流式处理上,Storm有着不可比拟的优势,而在大批量内存处理方面Spark Streaming有不小的优势。但由于Databricks的强势推广加上Spark Streaming本身的快速更新,Spark Streaming受到极大的关注,非常火爆,而Storm的模型决定了它的应用范围相对要比Spark Streaming小很多(除了少数大公司,真正的实时流处理的需求并不多,而这些大公司又倾向于自己开发,不使用原生的架构),但Storm的好处在于它可以像MapReduce一样定义一套实时流处理的标准接口,大多数实时计算系统(包括Twitter新推出的Heron)都遵循Topology-Spout-Bolt这一模式,这个体系是很有价值的。