数据的时效性node
平常工做中,咱们通常会先把数据储存在一张表中,而后对这张表的数据进行加工、分析。既然数据要储存在表中,就有时效性这个概念。
若是咱们处理的是年级别的数据,好比人口分析、宏观经济分析,那么数据最新日期距今晚个一两周、甚至一两个月都没什么关系。
若是咱们处理的是天级别的数据,好比各大网站的用户偏好分析、零售供销分析,通常晚个几天也是能够的,即 T+N 更新。
若是是小时级别的数据,对时效性要求就更高了,好比金融风控,涉及到资金的安全,必须有一张小时级别的数据。
那么还有没有要求更高的?固然有了,好比风险监测,网站必须有实时监测系统,一旦有攻击,就必须马上采起措施,双十一或者周年庆的时候,各大电商平台都经历着严峻的流量考验,也必须对系统进行实时的监测。此外,网站的实时个性化推荐、搜索引擎中也对实时性有极高的要求。
在这种场景下,传统的数据处理流程——先收集数据,而后放到DB中,再取出来分析——就没法知足这么高的实时要求。
流式计算,在实时或者准实时的场景下,应运而生。算法
(1)与批量计算那样慢慢积累数据不一样,流式计算将大量数据平摊到每一个时间点上,连续地进行小批量的进行传输,数据持续流动,计算完以后就丢弃。
(2) 批量计算是维护一张表,对表进行实施各类计算逻辑。流式计算相反,是必须先定义好计算逻辑,提交到流式计算系统,这个计算做业逻辑在整个运行期间是不可更改的。
(3) 计算结果上,批量计算对所有数据进行计算后传输结果,流式计算是每次小批量计算后,结果能够马上投递到在线系统,作到实时化展示。数据库
(1) 流式计算流程
① 提交流计算做业。
② 等待流式数据触发流计算做业。
③ 计算结果持续不断对外写出。编程
(2) 流式计算特色
① 实时、低延迟
② 无界,数据是不断无终止的
③ 连续,计算持续进行,计算完以后数据即丢弃数组
Apache Storm 安全
在Storm中,先要设计一个用于实时计算的图状结构,咱们称之为拓扑(topology)。这个拓扑将会被提交给集群,由集群中的主控节点(master node)分发代码,将任务分配给工做节点(worker node)执行。一个拓扑中包括spout和bolt两种角色,其中spout发送消息,负责将数据流以tuple元组的形式发送出去;而bolt则负责转换这些数据流,在bolt中能够完成计算、过滤等操做,bolt自身也能够随机将数据发送给其余bolt。由spout发射出的tuple是不可变数组,对应着固定的键值对。性能优化
Apache Flink 网络
Flink 是一个针对流数据和批数据的分布式处理引擎。它主要是由 Java 代码实现。对 Flink 而言,其所要处理的主要场景就是流数据,批数据只是流数据的一个极限特例而已。再换句话说,Flink 会把全部任务当成流来处理,这也是其最大的特色。Flink 能够支持本地的快速迭代,以及一些环形的迭代任务。而且 Flink 能够定制化内存管理。在这点,若是要对比 Flink 和 Spark 的话,Flink 并无将内存彻底交给应用层。这也是为何 Spark 相对于 Flink,更容易出现 OOM 的缘由(out of memory)。就框架自己与应用场景来讲,Flink 更类似与 Storm。架构
Apache Spark Streaming 框架
Spark Streaming是核心Spark API的一个扩展,它并不会像Storm那样一次一个地处理数据流,而是在处理前按时间间隔预先将其切分为一段一段的批处理做业。Spark针对持续性数据流的抽象称为DStream(DiscretizedStream),一个DStream是一个微批处理(micro-batching)的RDD(弹性分布式数据集);而RDD则是一种分布式数据集,可以以两种方式并行运做,分别是任意函数和滑动窗口数据的转换。
Storm, Flink, Spark Streaming的对比图
Storm, Flink, Spark Streaming的选择
若是你想要的是一个容许增量计算的高速事件处理系统,Storm会是最佳选择。
若是你必须有状态的计算,刚好一次的递送,而且不介意高延迟的话,那么能够考虑Spark Streaming,特别若是你还计划图形操做、机器学习或者访问SQL的话,Apache Spark的stack容许你将一些library与数据流相结合(Spark SQL,Mllib,GraphX),它们会提供便捷的一体化编程模型。尤为是数据流算法(例如:K均值流媒体)容许Spark实时决策的促进。
Flink支持增量迭代,具备对迭代自动优化的功能,在迭代式数据处理上,比Spark更突出,Flink基于每一个事件一行一行地流式处理,真正的流式计算,流式计算跟Storm性能差很少,支持毫秒级计算,而Spark则只能支持秒级计算。
Spark Streaming 是Spark 核心API的一个扩展,能够实现高吞吐量的、具有容错机制的实时流数据的处理。支持多种数据源获取数据,包括Kafka、Flume、Zero MQ,Kinesis以及TCP Sockets,从数据源获取数据以后,可使用诸如map、reduce、join和window等高级函数进行复杂算法的处理。最后还能够将处理结果存储到文件系统,数据库和现场仪表盘。
在”One Stack rule them all”的基础上,可使用Spark的其余子框架,如集群学习、图计算等,对流数据进行处理。
Spark的各个子框架都是基于Spark Core的,Spark Streaming在内部的处理机制是,接收实时流的数据,并根据必定的时间间隔拆分红一批批的数据,而后经过Spark Enging处理这些批数据,最终获得处理后的一批批结果数据。 对应的批数据,在Spark内核对应一个RDD实例,所以,对应流数据的DStream能够当作是一组RDDS,即RDD的一个序列。通俗点理解的话,在流数据分红一批一批后,经过一个先进先出的队列,而后Spark Enging从该队列中依次取出一个个批数据,把批数据封装成一个个RDD,而后进行处理,这是一个典型的生产者/消费者模型,对应的就有生产者消费者模型的问题,即如何协调生产速率和消费速率。
离散流(discretized stream)或DStream
这是SparkStraming对内部持续的实时数据流的抽象描述,即咱们处理的一个实时数据流,在Spark Streaming中对应于一个DStream实例。
批数据(batch data)
这是化整为零的第一步,将实时流数据以时间片为单位进行分批,将流处理转化为时间片数据的批处理。随着持续时间的推移,这些处理结果就造成了对应的结果数据流了。
时间片或批处理时间间隔(batch interval)
这是人为地对数据流进行定量的标准,以时间片做为咱们拆分数据流的依据。一个时间片的数据对应一个RDD实例。
窗口长度(window length)
一个窗口覆盖的流数据的时间长度。必须是批处理时间间隔的倍数。
滑动时间间隔
前一个窗口到后一个窗口所通过的时间长度。必须是批处理时间间隔的倍数。
Input DStream
一个input DStream是一个特殊的DStream,将Spark Streaming链接到一个外部数据源来读取数据。
在Spark Streaming中,数据处理是按批进行的,而数据采集是逐条进行的,所以在Spark Streaming中会事先设置好批处理间隔(batch duration),当超过批处理间隔的时候就会把采集到的数据汇总起来称为一批数据交个系统区处理。
对于窗口操做而言,在其窗口内部会有N个批处理数据,批处理数据的大小由窗口间隔(window duration)决定,而窗口间隔指的就是窗口的持续时间,在窗口操做中,只有窗口的长度知足了才会触发批处理的处理。除了窗口的长度,窗口操做还有另外一个重要的参数就是滑动间隔(slide duration),它指的是通过多长时间窗口滑动一次造成新的窗口,滑动窗口默认状况下和批次间隔的相同,而窗口间隔通常设置的要比它们两个大。在这里必须注意的一点是滑动间隔和窗口间隔的大小必定得设置为批处理间隔的整数倍。
Spark Streaming是一个对实时数据流进行高通量、容错处理的流式处理系统,能够对多种数据源(如Kafka、Flume、Zero MQ和TCP套接字)进行相似Map、Reduce和Join等复杂操做,并将结果保存到外部文件系统、数据库或应用到实时仪表盘。
计算流程
Spark Streaming是将流式计算分解成一系列短小的批处理做业。这里的批处理引擎是Spark Core,也就是把Spark Streaming的输入数据按照batch size(如1秒)分红一段一段的数据(Discretized Stream),每一段数据都转换成Spark中的RDD(Resilient Distrbute Dataset),而后将Spark Streaming中对DStream的Transformation操做变为针对Spark中对RDD的Transformation操做,将RDD通过操做变成中间结果保存在内存中。整个流式计算根据业务的需求能够对中间的结果进行叠加或者存储到外部设备。
容错性
对于流式计算来讲,容错性相当重要。首先咱们要明确一下Spark中RDD的容错性机制。每个RDD都是一个不可变的分布式可重算的数据集,其记录着肯定性的操做继承关系(lineage),因此只要输入数据是可容错的,那么任意一个RDD的分区(Partition)出错或不可用,都是能够利用原始输入数据经过转换操做而从新算出的。
对于Spark Streaming来讲,其RDD的传承关系以下图所示,图中的每个椭圆形表示一个RDD,椭圆形中的每一个圆形表明一个RDD中的一个Partition,图中的每一列的多个RDD表示一个DStream(图中有三个DStream),而每一行最后一个RDD则表示每个Batch Size锁产生的中间结果RDD。咱们能够看到图中的每个RDD都是经过lineage相链接的,因为Spark Streaming输入数据能够来自磁盘,例如HDFS(多份拷贝)或是来自与网络的数据流(Spark Streaming会将网络输入数据的每个数据流拷贝两份到其余的机器)都能保证容错性,因此RDD中任意的Partition出错,均可以并行地在其余机器上将缺失的Partition计算出来。这个容错恢复方式比连续计算模型(如Storm)的效率更高。
实时性
对于实时性的讨论,会牵涉到流式处理框架的应用场景。Spark Streaming将流式计算分解成多个Spark Job,对于每一段数据的处理都会通过Spark DAG图分解以及Spark的任务集的调度过程。对于目前版本的Spark Streaming而言,其最小的Batch Size的选取在0.5 ~ 2秒之间(Stom目前最小的延迟在100ms左右),因此Spark Streaming可以知足除对实时性要求很是高(如高频实时交易)以外的全部流式准实时计算场景。
扩展性与吞吐量
Spark目前在EC2上已经可以线性扩展到100个节点(每一个节点4Core),能够以数秒的延迟处理6GB/s的数据量(60M records/s),其吞吐量也比流行的Storm高2~5倍,如下是Berkeley利用WordCount和Grep两个用例所作的测试。
与RDD同样,DStream一样也能经过persist()方法将数据流存放在内存中,默认的持久化方法是MEMORY_ONLY_SER,也就是在内存中存放数据同时序列化的方式,这样作的好处是遇到须要屡次迭代计算的程序时,速度优点十分的明显。而对于一些基于窗口的操做,如reduceByWindow、reduceByKeyAndWindow,以及基于状态的操做,如updateStateByKey,其默认的持久化策略就是保存在内存中。
对于来自网络的数据源(Kafka、Flume、sockets等),默认的持久化策略是将数据保存在两台机器上,这也是为了容错性而设计的。
另外,对于窗口和有状态的操做必须checkpont,经过StreamingContext的checkpoint来指定目录,经过DStream的checkpoint指定间隔时间,间隔必须是滑动间隔(slide interval)的倍数。
1,优化运行时间
增长并行度
确保使用整个集群的资源,而不是把任务集中在几个特定的节点上。对于包含shuffle的操做,增长其并行度以确保更为充分的使用集群资源。
减小数据序列化,反序列化的负担
Spark Streaming默认将接受到的数据序列化后存储,以减小内存的使用。可是序列化和反序列化须要更多的CPU时间,所以更加高效的序列化方式和自定义的序列化接口以更高效的使用CPU。
设置合理的batch duration(批处理时间)
在Spark Streaming中,Job之间有可能存在依赖关系,后面的Job必须确保前面的做业执行结束后才能提交。若前面的Job执行的时间超出了批处理时间间隔,那么后面的Job就没法按时提交,这样就会进一步拖延接下来的Job,形成后续Job的阻塞。所以设置一个合理的批处理间隔以确保做业可以在这个批处理间隔内结束是必须的。
2,优化内存使用
控制batch size(批处理间隔内的数据量)
Spark Streaming会把批处理间隔内接收到的全部数据存放在Spark内部的可用内存区域中,所以必须确保当前节点Spark的可用内存中至少能容纳这个批处理时间间隔内的全部数据,不然必须增长新的资源以提升集群的处理能力。
及时清理再也不使用的数据
前面讲到Spark Streaming会将接受的数据应及时清理,以确保Spark Streaming有富余的可用内存空间。经过设置合理的spark.cleaner.ttl时长来及时清理超时的无用数据,这个参数须要当心设置以避免后续操做中所须要的数据被超时错误处理。
观察及适当调整GC策略 GC会影响Job的正常运行,可能延长Job的执行时间,引发一系列不可预料的问题。观察GC的运行状况,采用不一样的GC策略以进一步减少内存回收对Job运行的影响。