我对在Flink上加入两个流有疑问。我使用了有时需要的两个不同的数据流 加入他们。每个数据流都已标记有唯一的ID,作为这些流之间的连接点。 没有窗口的概念,因此为了连接这两个数据流,我要做 first.connect(second).keyBy(0,0)。
当我得到正确的结果时,这似乎起作用,但是我的担忧是长期的。我没有明确保留任何 进行联接的运算符(coFlatMap)上的状态,但是如果假设一个流(例如,第一个)提供唯一 id和第二个未能提供连接的id(我想对于那些已经加入的操作员会丢弃任何内部状态)?内存/状态占用空间是否持续增长或存在某种过期机制?
如果是这种情况,我该如何解决这个问题?还是可以建议我另一种方法?
答案 0 :(得分:0)
有几种方法可以实现这种连接。
使用CoProcessFunction。当密钥的第一条记录到达时,您将其存储在状态中,并注册一个在x分钟/小时/天之后触发的计时器。当第二条记录到达时,您将执行联接并清除状态。如果第二条记录未到达,则在计时器触发时将调用onTimer()
方法。此时,您可以只清除状态并返回(INNER JOIN语义),也可以转发填充有null
值的第一条记录(OUTER JOIN语义),清除状态并返回。计时器用作安全网,以便能够在某些时候消除状态。这取决于您的要求,您要等待多长时间才能等待第二条记录到达。
表API或SQL提供了一个时间窗口联接(Table API,SQL),其工作方式与我在1中所述的类似。区别在于窗口联接实现将尝试连接在连接间隔期间到达的所有记录(即,每个输入流中有多个记录),因此可以使状态保持更长的时间。但是,一旦时间超过了连接间隔,它将清除状态。
Flink 1.6.0(将于2018年8月初发布)将包括一个用于DataStream API的interval join,其作用类似于Table API的窗口联接(相似的逻辑,不同的名称)。与自定义实现相比,状态保持的时间也比自定义实现更长,自定义实现是基于这样的假设,即每个键在每侧仅出现一次。
我会选择方法1,因为它可以提高内存效率,并且仍然相当容易实现。