保存点

flink run -s hdfs://zhumei00:9000/flink/savepoints/savepoint-2084e7-591930867f28/_metadata flink-demo-stateful.jar
package org.example.join

import org.apache.flink.api.common.state.ValueStateDescriptor
import org.apache.flink.api.scala.typeutils.Types
import org.apache.flink.streaming.api.TimeCharacteristic
import org.apache.flink.streaming.api.functions.co.CoProcessFunction
import org.apache.flink.streaming.api.scala._
import org.apache.flink.util.Collector

object TwoStreamsJoin {

  // 订单支付事件
  case class OrderEvent(orderId: String,
                        eventType: String,
                        eventTime: Long)

  // 第三方支付事件,例如微信,支付宝
  case class PayEvent(orderId: String,
                      eventType: String,
                      eventTime: Long)
  // 用来输出没有匹配到的订单支付事件
  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 = env
      .fromElements(
        OrderEvent("order_1", "pay", 2000L),
        OrderEvent("order_2", "pay", 5000L),
        OrderEvent("order_3", "pay", 6000L)
      )
      .assignAscendingTimestamps(_.eventTime)
      .keyBy(_.orderId)

    val pays = env
      .fromElements(
        PayEvent("order_4", "weixin", 9000L),
        PayEvent("order_1", "weixin", 7000L),
        PayEvent("order_2", "weixin", 8000L)

      )
      .assignAscendingTimestamps(_.eventTime)
      .keyBy(_.orderId)

    val processed = orders
      .connect(pays)
      .process(new MatchFunction)

    processed.print()

    processed.getSideOutput(unmatchedOrders).print()

    processed.getSideOutput(unmatchedPays).print()

    env.execute()
  }

  class MatchFunction extends CoProcessFunction[OrderEvent, PayEvent, String] {

    // 用来保存到来的订单支付事件
    lazy val orderState = getRuntimeContext.getState(
      new ValueStateDescriptor[OrderEvent]("order-state", Types.of[OrderEvent])
    )

    // 用来保存到来的第三方支付事件
    lazy val payState = getRuntimeContext.getState(
      new ValueStateDescriptor[PayEvent]("pay-state", Types.of[PayEvent])
    )

    // 处理订单支付流的
    override def processElement1(order: OrderEvent, ctx: CoProcessFunction[OrderEvent, PayEvent, String]#Context, out: Collector[String]): Unit = {
      val pay = payState.value()

      // pay 和 order 的订单ID是一样的
      if (pay != null) {
        payState.clear()
        out.collect("订单ID为 " + order.orderId + " 的两条流对账成功!")
      } else {
        orderState.update(order)
        // 等待另一条流对应的事件,5秒钟
        ctx.timerService().registerEventTimeTimer(order.eventTime + 5000L)
      }
    }

    // 处理第三方支付流的
    override def processElement2(pay: PayEvent, ctx: CoProcessFunction[OrderEvent, PayEvent, String]#Context, out: Collector[String]): Unit = {
      val order = orderState.value()

      if (order != null) {
        orderState.clear()
        out.collect("订单ID为 " + pay.orderId + " 的两条流对账成功!")
      } else {
        payState.update(pay)
        ctx.timerService().registerEventTimeTimer(pay.eventTime + 5000L)
      }
    }

    override def onTimer(timestamp: Long, ctx: CoProcessFunction[OrderEvent, PayEvent, String]#OnTimerContext, out: Collector[String]): Unit = {
      if (orderState.value() != null) {
        ctx.output(unmatchedOrders, "订单ID为 " + orderState.value().orderId + " 的两条流没有对账成功!")
        orderState.clear()
      }
      if (payState.value() != null) {
        ctx.output(unmatchedPays, "订单ID为 " + payState.value().orderId + " 的两条流没有对账成功!")
        payState.clear()
      }
    }
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值