Apache spark 如何构建一个包含两个kafka流的数据帧;钥匙;列和剩余列是最新的值

Apache spark 如何构建一个包含两个kafka流的数据帧;钥匙;列和剩余列是最新的值,apache-spark,pyspark,spark-streaming,spark-structured-streaming,spark-streaming-kafka,Apache Spark,Pyspark,Spark Streaming,Spark Structured Streaming,Spark Streaming Kafka,我的Spark 2.4.x(pyspark)应用程序需要: 输入是两个卡夫卡主题,输出是一个卡夫卡主题 “流表”在哪里 有一个逻辑键和 其余列应为任一流的最新值 亚秒延迟。测试表明,当水印不存在时,这是可以实现的 用过 这似乎是一件基本的事情,但它并不完全适合我 例子: 注意:在下面的示例中,T1、T2和T2时间点可以相隔秒/分钟/小时 T1)在时间T1 KafkaPriceTopic获取1条消息负载(我们称之为P1): {“SecurityCol”:“Sec1”、“priceqnocol

我的Spark 2.4.x(pyspark)应用程序需要:

  • 输入是两个卡夫卡主题,输出是一个卡夫卡主题
  • “流表”在哪里
    • 有一个逻辑键和
    • 其余列应为任一流的最新值
  • 亚秒延迟。测试表明,当
    水印不存在时,这是可以实现的
    用过
  • 这似乎是一件基本的事情,但它并不完全适合我


    例子: 注意:在下面的示例中,T1、T2和T2时间点可以相隔秒/分钟/小时

    T1)在时间T1

    KafkaPriceTopic获取1条消息负载(我们称之为P1):
    {“SecurityCol”:“Sec1”、“priceqnocol”:“1”、“PriceCol”:“101.5”}

    KafkaVolumeTopic1带有有效负载的消息(我们称之为V1):
    {“SecurityCol”:“Sec1”、“VolumeSeqNoCol”:“1”、“VolumeCol”:“50”}

    我希望得到一个结果
    数据帧
    ,如下所示:

    +-----------+--------+---------+-------------+--------------+ 
    |SecurityCol|PriceCol|VolumeCol|PriceSeqNoCol|VolumeSeqNoCol|  
    +-----------+--------+---------+-------------+--------------+ 
    |Sec1       |101.5   |50       |1            |1             |
    +-----------+--------+---------+-------------+--------------+ 
    
    T2)卡夫卡普里塞托普1信息(P2):
    {“SecurityCol”:“Sec1”、“PriceSeqNoCol”:“2”、“PriceCol”:“101.6”}

    结果
    数据帧

    +-----------+--------+---------+-------------+--------------+ 
    |SecurityCol|PriceCol|VolumeCol|PriceSeqNoCol|VolumeSeqNoCol|  
    +-----------+--------+---------+-------------+--------------+ 
    |Sec1       |101.6   |50       |2            |1             |
    +-----------+--------+---------+-------------+--------------+ 
    
    +-----------+--------+---------+-------------+--------------+ 
    |SecurityCol|PriceCol|VolumeCol|PriceSeqNoCol|VolumeSeqNoCol|
    +-----------+--------+---------+-------------+--------------+
    |Sec1       |101.6   |60       |2            |2             |
    +-----------+--------+---------+-------------+--------------+ 
    
    注意P1不再相关

    T3)卡夫卡沃卢梅托皮克1信息V2
    {“SecurityCol”:“Sec1”、“VolumeSeqNoCol”:“2”、“VolumeCol”:“60”}

    结果
    数据帧

    +-----------+--------+---------+-------------+--------------+ 
    |SecurityCol|PriceCol|VolumeCol|PriceSeqNoCol|VolumeSeqNoCol|  
    +-----------+--------+---------+-------------+--------------+ 
    |Sec1       |101.6   |50       |2            |1             |
    +-----------+--------+---------+-------------+--------------+ 
    
    +-----------+--------+---------+-------------+--------------+ 
    |SecurityCol|PriceCol|VolumeCol|PriceSeqNoCol|VolumeSeqNoCol|
    +-----------+--------+---------+-------------+--------------+
    |Sec1       |101.6   |60       |2            |2             |
    +-----------+--------+---------+-------------+--------------+ 
    
    注意P1V1不再相关


    什么有效
  • 从有效负载中提取json(
    get_json\u object
    暂时),
    连接两个主题的流
    
  • 不过。这将产生(不带
    水印
    )一个
    数据帧
    ,它具有所有 Sec1收到的价格和数量,而不仅仅是最新的价格和数量
  • 所以后面是一个
    groupBy(…).agg(last(…),…)
    。但我坚持下去了 仅获取一行最新值
  • dfKafka1=spark.readStream.format(“kafka”)#剩余选项等
    .load()
    .选择(…)#将字段提取为列“
    dfKafka2=spark.readStream.format(“kafka”)#剩余选项等
    .load()
    .选择(…)#将字段提取为列“
    dfResult=dfKafka1.join(dfKafka2,“SecurityCol”)
    #结构化流媒体还不允许在加入后使用groupBy,因此请编写中间kafka主题
    dfResult.writestream.format(“卡夫卡”)#剩余选项
    .trigger(processingTime=“1秒”)
    .start()
    #加载中间卡夫卡主题
    dfKafkaResult=spark.readStream.format(“kafka”)#剩余选项
    .load()
    .为cols选择(…)#获取json_对象
    .groupBy(“SecurityCol”)#定义agg cols的“密钥”
    .agg(最后一列(“价格列”),#每列的最新值
    最后(“PriceSexNocol”),
    最后(“VolumeCol”),
    最后一个(“卷号”))
    

    问题 然而,最后的
    agg
    last()
    并没有始终如一地发挥作用

  • 当KafkaVolumeTopic收到一条新消息时,结果可能与 卡夫卡普里塞托普传来的一条老消息
  • 此外,
    orderBy
    /sort不能在没有聚合的流上使用

  • 限制
  • 在加入
    之前,我不能
    groupBy
    ,因为这需要
    带有水印
    ,我想我的应用程序不能使用
    水印
    。理论基础:
    • 应用程序应该能够在一天中的任何时间加入给定SecurityCol的两个主题。
      • 如果PriceTopic在上午9点收到消息,VolumeTopic在上午10点收到消息
      • 我希望这两个人能一起出席
    • 水印限制以
      append
      模式发送数据的时间。所以不能在这里使用水印,因为时间范围是一整天

  • 有什么想法吗