(图1:SparkStreaming生态,viaSpark官网)
(图2:Flink生态,viaFlink官网)SparkStreaming是微批处理,运行的时候需要指定批处理的时间,每次运行job时处理一个批次的数据,流程如图3所示:
(图3:viaSpark官网)Flink是基于事件驱动的,事件可以理解为消息。事件驱动的应用程序是一种状态应用程序,它会从一个或者多个流中注入事件,通过触发计算更新状态,或外部动作对注入的事件作出反应。
(图4:viaFink官网)编程模型对比,主要是对比Flink和SparkStreaming两者在代码编写上的区别。基于receiverdstream;基于directdstream。以上两种模型编程机构近似,只是在API和内部数据获取有些区别,新版本的已经取消了基于receiver这种模式,企业中通常采用基于directDstream的模式。
(图5:Spark任务调度)对于job的调度执行有fifo和fair两种模式,Task是根据假设每个SparkStreaming任务消费的Kafkatopic有四个分区,中间有一个transform操作(如map)和一个reduce操作,如图6所示:
(图6)假设有两个executor,其中每个executor三个核,那么每个批次相应的task运行位置是固定的吗?是否能预测?由于数据本地性和调度不确定性,每个批次对应Kafka分区生成的task运行位置并不是固定的。
(图7)如图7所示有一个由datasource、MapFunction和ReduceFunction组成的程序,datasource和MapFunction的并发度都为4,而ReduceFunction的并发度为3。
(图8)SparkStreaming只支持处理时间,Structuredstreaming支持处理时间和事件时间,同时支持watermark机制处理滞后数据。Flink支持三种时间机制:事件时间、注入时间、处理时间,同时支持watermark机制处理滞后数据。
(图9)其中确认的是SparkStreaming与Kafka0.8版本结合不支持动态分区检测,与0.10版本结合支持,接着通过源码分析。
(图10)在FlinkKafkaConsumerBase的run方法中,创建了kafkaFetcher,实际上就是消费者:this.kafkaFetcher=createFetcher(接是创建了一个线程,该线程会定期检测Kafka新增分区,然后将其添加到kafkaFetcher里。if(discoveryIntervalMillis!
(图11)下面详细讲解Flink的两段提交思路:
(图12)如图12所示,Flinkcheckpointing开始时便进入到pre-commit阶段。具体来说,一旦checkpoint开始,Flink的JobManager向输入流中写入一个checkpointbarrier,将流中所有消息分割成属于本次checkpoint的消息以及属于下次checkpoint的,barrier也会在操作算子间流转。
(图13)当结合外部系统的时候,外部系统必须要支持可与两阶段提交协议捆绑使用的事务。显然本例中的sink由于引入了kafkasink,因此在预提交阶段datasink必须预提交外部事务。如下图:
(图14)当barrier在所有的算子中传递一遍,并且触发的快照写入完成,预提交阶段完成。所有的触发状态快照都被视为checkpoint的一部分,也可以说checkpoint是整个应用程序的状态快照,包括预提交外部状态。出现故障可以从checkpoint恢复。下一步就是通知所有的操作算子checkpoint成功。
(图15)以上就是Flink实现恰一次处理的基本逻辑。消费者消费的速度低于生产者生产的速度,为了使应用正常,消费者会反馈给生产者来调节生产者生产的速度,以使得消费者需要多少,生产者生产多少。(*backpressure后面一律称为背压。)SparkStreaming跟Kafka结合是存在背压机制的,目标是根据当前job的处理情况来调节后续批次的获取Kafka消息的条数。
>
领取专属 10元无门槛券
私享最新 技术干货