目录:apache beam 个人使用经验总结目录和入门指导(Java)
输入时刻概念
对于beam里的数据集里的每个数据,都会附带1个Instant成员(以下称为输入时刻),指明了该条数据输入时的时间戳(单位毫秒)。
如果是有限数据集(批处理方式输入的),且未没手动设置输入时刻, 则默认输入时刻全部相同。
如果是无限流式数据集,例如kafka,会根据到达的时间来设置输入时刻。
窗口则就是根据输入时刻来进行划分的。
伪造流式数据
因为用kafka做输入数据时,不好精确地控制输入时间
所以理解窗口概念和举例之前,我们先学习如何伪造流式数据。、
首先,我们造如下1个KV列表:
里面的key就代表了输入时刻,value是字符串展示。
接着用withTimestamps给这些输入元素设置输入时间(单位毫秒),并把kv转成v
这样1个流式数据就伪造好了, 我们就可以忽略绝对时间,只考虑相对的那些时间(即与NOW_TIME相对的时间间隔)
窗口
窗口的使用为pcollection.apply(Window.into(WindowsFn))
我们的例子中,会根据设置的窗口,把窗口内的数据合成1个列表并输出。
- 合成列表的transform使用Combine.globally(Sample.<String>anyCombineFn(100)).withoutDefaults()
- 而输出的话,我们会打印出列表并且加上该窗口内输入时刻的打印。
代码如下,后面我们介绍3种窗口时就只展示pTimeStrByWindow的apply过程:
固定时间窗口
固定时间窗口表示数据流中一致的连续、不重叠的时间间隔。
最简单的窗口形式开水奇偶固定时间窗口:如下图所示,有1个持续更新的时间戳PCollection,每个窗口可以捕获(例如)所有时间戳在30s时间间隔内的元素。
我们的例子里以1秒为固定窗口时间。
则显然分组情况应给为0.999一组, 1.0、1.001、1.999为一组,以此类推。
固定窗口的windowsFn为FixedWindows
固定间隔通过Duration去设置,里面还可以设置分钟间隔、小时间隔等(standardXXX())。
固定窗口的代码如下:
打印结果如下:
结果正确
滑动时间窗口
滑动时间窗口也表示数据流中的时间间隔; 然而,滑动时间窗口可以重叠。 例如,每个窗口可能捕获五分钟的数据,但是每十秒钟会启动一个新窗口。 滑动窗口开始的频率称为周期。 因此,示例中的窗口的时间长度为5分钟,滑动周期为10秒钟。
由于多个窗口重叠,数据集中的大多数元素将属于多个窗口。 这种窗口对于计算不断变化的数据的均值非常有用; 使用滑动时间窗口,可以在示例中计算过去5分钟的数据的运行平均值,每10秒更新一次。
本文中以2秒窗口、滑动周期为1秒做例子。
对于之前所提到的0.999、1、1.001、1.999、2.0、2.5、3.0、4.0、5.0这串流式数据
所划分的窗口区间如下:
- 0.999属于[-1s,1s)区间
- 0.999、1、1.001、1.999属于[0s,2s)区间
- 1、1.001、1.999、2.0、2.5属于[1s,3s)区间
- 2.0、2.5、3.0属于[2s,4s)区间
- 3.0、4.0属于[3s,5s)区间
- 4.0、5.0属于[4s,6s)区间
- 5.0属于[5s,7s)区间
因此最终应该会划分出7个窗口。
滑动窗口windowsFn使用SlidingWindows.of(窗口总长).every(窗口启动间隔时间),代码如下:
且窗口总长要大于窗口启动间隔时间,否则会报错,因为总厂比间隔小的话,会有流式数据丢失的情况。
结果打印如下:
与前面列出的一致。
会话时间窗口
会话窗口是一种在时间上非连续的窗口。 窗口的起始点以收到第一条数据开始, 直到x秒(会话结束间隔)内没有收到新的数据为结束点。 这种窗口适用于一些非周期规律性的流式数据
以本文例子为例0,对于0.999、1、1.001、1.999、2.0、2.5、3.0、4.0、5.0这串数据
0,999是第一次收到的数据,以此时为起始点,直到3.0s才结束, 因为3.0和4.0的间隔已经超过1秒的差距了。
之后4.0开始为起始点开始新的窗口,因为与下一个数据5.0s相差1秒所以直接结束
同理5.0也是1个窗口
因此会分成3个窗口:
- 0.999、1、1.001、1.999、2.0、2.5、3.0
- 4.0
- 5.0
会话窗口使用Sessions.withGapDuration(Duration.standardSeconds(会话结束间隔))
代码如下:
打印结果如下:
正确。
单一全局窗口
任何非流式的批处理有限数据集默认都是单一全局窗口, 即所有数据都在1个窗口内。
如果要对把某流式数据放进单一全局窗口,前提是你确认这一次计算过程中, 你是知道流式数据会在某个触发条件下结束,这涉及到触发器概念,因此这一块放到apache beam入门之触发器中去讲
单一全局窗口实现方式: