Flink流计算编程--在WindowedStream中体会EventTime与ProcessingTime

一、Flink流处理简介

Flink流处理的API叫做DataStream,可以在保证Exactly-Once的前提下提供高吞吐、低延时的实时流处理。用Flink作为流处理框架成功的案例可参考Flink母公司–Data Artisans官方blog中的2篇文章:
How we selected Apache Flink as our Stream Processing Framework at the Otto Group Business Intelligence Department
RBEA: Scalable Real-Time Analytics at King

二、Flink中的Time模型

Flink中提供了3种时间模型:EventTime、ProcessingTime、与Ingestion Time。底层实现上分为2种:Processing Time与Event Time,而Ingestion Time本质上也是一种Event Time,可以通过官方文档上的一张图展现是3者的区别:
这里写图片描述
Event Time:事件产生的时间,即数据产生时自带时间戳,例如‘2016/06/17 11:04:00.960’
Ingestion Time:数据进入到Flink的时间,即数据进入source operator时获取时间戳
Processing Time:系统时间,与数据本身的时间戳无关,即在window窗口内计算完成的时间(默认的Time)

关于Flink中的Time,可以参考官方文档中的说明:Event Time

关于Event Time,需要指出的是:数据产生的时间,编程时首先就是要告诉Flink,哪一列作为Event Time列,同时分配时间戳(TimeStamp)并发出水位线(WaterMark),来跟踪Event Time。简单理解,就是以Event Time列作为时间。水位线既然是用来标记Event Time的,那么Event Time在产生时有可能因为网络或程序错误导致的时间乱序,即Late Element的产生,因此WaterMark分为有序与无序2种:
这里写图片描述

这里写图片描述

关于Late Element,举个例子说明:数据随着时间的流逝而产生,即数据的产生本是升序的,当Flink采用Event Time作为时间模型时,理论上也应该是升序的数据不断的进行计算。但是突然有个“延迟的”数据进入到了Flink,此时时间窗口已过,那么这个“延迟的”数据就不会被正确的计算。
对于这些数据,流处理的可能无法实时正确计算,因为WarterMark不可能无限制的等待Late Element的到来,所以可以通过之后的批处理(batch)对已经计算的数据进行更正。

关于流计算、时间模型与窗口的说明,可以参考:
Streaming 101

淌水采水蛭的3个女人

Streaming 102

密苏里河上的船夫

三、Flink流处理编程的步骤

共5个步骤:
1、获取DataStream的运行环境
2、从Source中创建DataStream
3、在DataStream上进行transformation操作
4、将结果输出
5、执行流处理程序

四、程序说明

说明:
IDE:IntelliJ IDEA Community Edition(From JetBrains)
开发语言: Scala 2.10
运行环境:Flink 1.0.3 集群(1个JobManager+2个TaskManager)
程序提交:客户端CLI
管理工具:maven 3.3.9

五、程序演示–体会Event Time

关键点:
设置Event time characteristic:

env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)

复写map方法,实现稍微复杂点的map transaction:

map(new EventTimeFunction)

分配timestamp以及watermark:

val timeValue = parsedStream.assignAscendingTimestamps(_._2)

在dataStream上运行keyBy操作,产生keyedStream,继而在keyedStream上运行window操作,产生windowedStream,此时,windowedStream包含的元素主要包含3方面:K->key,W->window,T->Iterable[(..)],即每个key在特定窗口内的元素的集合。不同的stream之间的互相调用,可以参考:
Flink 原理与实现:数据流上的类型和操作

这里写图片描述

在windowedStream上聚合sum:

val sumVolumePerMinute = timeValue
      .keyBy(_._1)
      .window(TumblingEventTimeWindows.of(Time.minutes(1)))
      .sum(3)
      .name("sum volume per minute")

运行程序,测试结果:
输入:

600000.SH,600000,20160520,93000960,1,39,173200,400,800,66,0,0,62420,76334,
  • 1
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值