一:简介
之前文章中提到JoinedStream与CoGroupedStream,例如下列代码:
dataStream.join(otherStream)
.where(0).equalTo(1)
.window(TumblingEventTimeWindows.of(Time.seconds(3)))
.apply { ... }
由于joinedStream与coGroupedStream来自于一个特定的window,且在一个关联上的key中实现,因此,Flink中的双流join一定是在一个基于Inner Join的key的前提下的操作。
双流Join中的Inner、Left、Right Join操作,实际上是指在特定的window范围内的join。即Join的主体是window范围,如果窗口内都没有数据,则不发生join。
二、具体实现
这里我通过2个Socket接收数据,模拟双流,共3个参数,代码如下:
if (args.length != 3) {
System.err.println("USAGE:\nSocketTextStreamJoinType <hostname> <port1> <port2>")
return
}
val hostName = args(0)
val port1 = args(1).toInt
val port2 = args(2).toInt
接下来,我们创建了2个case class,来模拟2个socket的输入流数据,代码如下:
case class StockTransaction(tx_time:String, tx_code:String,tx_value:Double)
case class StockSnapshot(md_time:String, md_code:String,md_value:Double)
最后要注意的地方就是如何实现Inner Join、Left Join与Right Join了。这里采用coGroup方式,通过对coGroupFunction中的2个Iterable集合判断是否为空来实现,例如:
if(scalaT1.nonEmpty && scalaT2.nonEmpty){
for(transaction <- scalaT1){
for(snapshot <- scalaT2){
out.collect(transaction.tx_code,transaction.tx_time, snapshot.md_time,transaction.tx_value,snapshot.md_value,"Inner Join Test")
}
}
}
}
三、完整的代码示例
package wikiedits
import java.text.SimpleDateFormat
import org.apache.flink.api.common.functions.CoGroupFunction
import org.apache.flink.streaming.api.TimeCharacteristic
import org.apache.flink.streaming.api.scala._
import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows
import org.apache.flink.streaming.api.windowing.time.Time
import org.apache.flink.util.Collector
object InnerLeftRightJoinTest {
// *************************************************************************
// PROGRAM
// *************************************************************************
def main(args : Array[String]) : Unit