package com.streamingjoin

import org.apache.flink.api.common.state.{ValueState, ValueStateDescriptor}
import org.apache.flink.streaming.api.TimeCharacteristic
import org.apache.flink.streaming.api.functions.co.KeyedCoProcessFunction
import org.apache.flink.streaming.api.scala._
import org.apache.flink.util.Collector /**
* 将五分钟之内的订单信息和支付信息进行对账,对不上的发出警告
*/
object TwoStreamJoinDemo { // 用来输出没有匹配到的订单支付事件
val unmatchedOrders = new OutputTag[String]("unmatched-orders")
// 用来输出没有匹配到的第三方支付事件
val unmatchedPays = new OutputTag[String]("unmatched-pays") def main(args: Array[String]): Unit = { val env = StreamExecutionEnvironment.getExecutionEnvironment
env.setParallelism(1)
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime) val orders: KeyedStream[OrderEvent, String] = env.fromElements(
OrderEvent("order_1", "pay", 2000L),
OrderEvent("order_2", "pay", 5000L),
OrderEvent("order_3", "pay", 6000L))
.assignAscendingTimestamps(_.eventTime)
.keyBy(_.orderId) val pays: KeyedStream[PayEvent, String] = env
.fromElements(
PayEvent("order_1", "weixin", 7000L),
PayEvent("order_2", "weixin", 8000L),
PayEvent("order_4", "weixin", 9000L)
)
.assignAscendingTimestamps(_.eventTime)
.keyBy(_.orderId) val processed: DataStream[String] = orders.connect(pays).process(new MatchFunction) processed.print()
processed.getSideOutput(unmatchedOrders).print()
processed.getSideOutput(unmatchedPays).print() env.execute() } //订单支付事件
case class OrderEvent(orderId: String,
eventType: String,
eventTime: Long) //第三方支付事件,例如微信,支付宝
case class PayEvent(orderId: String,
eventType: String,
eventTime: Long) //进入同一条流中的数据肯定是同一个key,即OrderId
//肯定会用到状态了
class MatchFunction extends KeyedCoProcessFunction[String, OrderEvent, PayEvent, String] { //状态的定义
lazy private val orderState: ValueState[OrderEvent] = getRuntimeContext.getState(new ValueStateDescriptor[OrderEvent]("orderState", classOf[OrderEvent]))
lazy private val payState: ValueState[PayEvent] = getRuntimeContext.getState(new ValueStateDescriptor[PayEvent]("payState", classOf[PayEvent])) override def processElement1(value: OrderEvent, ctx: KeyedCoProcessFunction[String, OrderEvent, PayEvent, String]#Context, out: Collector[String]): Unit = {
//从payState中查找数据,如果存在,说明匹配成功
val pay = payState.value()
if (pay != null) {
payState.clear()
out.collect("订单ID为 " + pay.orderId + " 的两条流对账成功")
} else {
//如果不存在,则说明可能对应的pay数据没有来,需要存入状态等待
//定义一个5min的定时器,到时候再匹配,如果还没匹配上,则说明匹配失败发出警告
orderState.update(value)
ctx.timerService().registerEventTimeTimer(value.eventTime + 5000)
}
} override def processElement2(value: PayEvent, ctx: KeyedCoProcessFunction[String, OrderEvent, PayEvent, String]#Context, out: Collector[String]): Unit = {
val order = orderState.value()
if (order != null) {
orderState.clear()
out.collect("订单ID为 " + order.orderId + " 的两条流对账成功!")
} else {
payState.update(value)
ctx.timerService().registerEventTimeTimer(value.eventTime + 5000)
}
} override def onTimer(timestamp: Long, ctx: KeyedCoProcessFunction[String, OrderEvent, PayEvent, String]#OnTimerContext, out: Collector[String]): Unit = { if (orderState.value() != null) {
//将警告信息发送到侧输出流中
ctx.output(unmatchedOrders, s"订单ID为 ${orderState.value().orderId} 的两条流没有对账成功!")
orderState.clear()
} if (payState.value() != null) {
ctx.output(unmatchedPays, s"订单ID为 ${payState.value().orderId} 的两条流没有对账成功! ")
payState.clear()
} }
} }

flink双流join的更多相关文章

  1. 面试官: Flink双流JOIN了解吗? 简单说说其实现原理

    摘要:今天和大家聊聊Flink双流Join问题.这是一个高频面试点,也是工作中常遇到的一种真实场景. 本文分享自华为云社区<万字直通面试:Flink双流JOIN>,作者:大数据兵工厂 . ...

  2. flink-----实时项目---day06-------1. 获取窗口迟到的数据 2.双流join(inner join和left join(有点小问题)) 3 订单Join案例(订单数据接入到kafka,订单数据的join实现,订单数据和迟到数据join的实现)

    1. 获取窗口迟到的数据 主要流程就是给迟到的数据打上标签,然后使用相应窗口流的实例调用sideOutputLateData(lateDataTag),从而获得窗口迟到的数据,进而进行相关的计算,具体 ...

  3. flink dataset join笔记

    1.dataset的join连接,通过key进行关联,一般情况下的join都是inner join,类似sql里的inner join key包括以下几种情况: a key expression a ...

  4. Apache Flink 漫谈系列 - JOIN 算子

    聊什么 在<Apache Flink 漫谈系列 - SQL概览>中我们介绍了JOIN算子的语义和基本的使用方式,介绍过程中大家发现Apache Flink在语法语义上是遵循ANSI-SQL ...

  5. Apache-Flink深度解析-JOIN 算子

    什么是JOIN 在<Apache Flink 漫谈系列 - SQL概览>中我对JOIN算子有过简单的介绍,这里我们以具体实例的方式让大家对JOIN算子加深印象.JOIN的本质是分别从N(N ...

  6. Flink sql 之 join 与 StreamPhysicalJoinRule (源码解析)

    源码分析基于flink1.14 Join是flink中最常用的操作之一,但是如果滥用的话会有很多的性能问题,了解一下Flink源码的实现原理是非常有必要的 本文的join主要是指flink sql的R ...

  7. Flink官网文档翻译

    http://ifeve.com/flink-quick-start/ http://vinoyang.com/2016/05/02/flink-concepts/ http://wuchong.me ...

  8. Flink 灵魂两百问,这谁顶得住?

    Flink 学习 https://github.com/zhisheng17/flink-learning 麻烦路过的各位亲给这个项目点个 star,太不易了,写了这么多,算是对我坚持下来的一种鼓励吧 ...

  9. Flink/CEP/规则引擎/风控

    基于 Apache Flink 和规则引擎的实时风控解决方案 ​ 对一个互联网产品来说,典型的风控场景包括:注册风控.登陆风控.交易风控.活动风控等,而风控的最佳效果是防患于未然,所以事前事中和事后三 ...

随机推荐

  1. 使用vue-preview报错Cannot read property 'open' of undefined

    最近在做一个vue项目中时,需要使用vue-preview插件制作缩略图,首先在终端使用npm i vue-preview -S指令安装了vue-preview插件,然后在main.js中,导入并引用 ...

  2. mysql - 按条件统计

    在表中分别统计mt =0 和 mt>0 的个数 方法一:select count(if(mt=0,1,null)) as a,count(if(mt>0,1,null)) as b fro ...

  3. python 连接mysql数据库操作

    import pymysql.cursors # 连接数据库 connect = pymysql.Connect( host='localhost', port=3306, user='root', ...

  4. 【用例】编写App测试用例的关注点

    编写App测试用例的关注点 如何做到测试用例的百分百覆盖一直是测试用例编写过程中的难点,首先在测试时我们经常会遇见一些常见的bug,那么我们可以在编写测试用例时考虑到这些点.    一:关于业务逻辑 ...

  5. Oracle 分页查询的一个实例

    1.分页模板 select * from ( select rownum as rn , a.* from( 某个表名) a) where rn between 0 and 6 2 某个表名 sele ...

  6. QT常用控件(三)——自定义控件封装

    引言 Qt已经提供了很多的基础控件供开发使用,而Qt原生的控件有时候并不能满足我们的需求,特别是在工业的运用上,比如我们需要一个日期时间的选择器,Qt虽然已经提供了原生的QDateTime控件,但这个 ...

  7. linux笔记全(无图版)

    1.ls 查看当前目录下的所有内容 黑色的是文件,蓝色的是文件夹,也就是目录 2.rm -f anaconda-ks. cfg 彻底删除文件(如不确定,则需要先保存备份,也就是快照) 3.ifconf ...

  8. 【LeetCode】169. 多数元素

    169. 多数元素 知识点:数组:排序:消消乐:分治: 题目描述 给定一个大小为 n 的数组,找到其中的多数元素.多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素. 你可以假设数组是非空的, ...

  9. Java代码操作zookeeper

    .personSunflowerP { background: rgba(51, 153, 0, 0.66); border-bottom: 1px solid rgba(0, 102, 0, 1); ...

  10. 使用Eclipse下载CRaSH源代码

    Eclipse for Java Developers (Juno)本身有一个eGit组件,通过它可以直接从Git源码库中下载源代码,以下载 CRaSH 为例说明: 从主页上的"Develo ...