Apache spark 如何从工作人员访问SparkSession?

Apache spark 如何从工作人员访问SparkSession?,apache-spark,pyspark,apache-spark-sql,spark-streaming,databricks,Apache Spark,Pyspark,Apache Spark Sql,Spark Streaming,Databricks,我在databricks中使用spark结构化流媒体。在这里,我使用foreach操作对每个数据记录执行一些操作。但是我传递给foreach的函数使用了SparkSession,但它抛出了一个错误:_pickle.PicklingError:无法序列化对象:异常:似乎您正试图从广播变量、操作或转换引用SparkContext。SparkContext只能在驱动程序上使用,不能在工作程序上运行的代码中使用 那么,有没有办法在foreach中使用SparkSession 编辑#1: foreach中

我在databricks中使用spark结构化流媒体。在这里,我使用foreach操作对每个数据记录执行一些操作。但是我传递给foreach的函数使用了SparkSession,但它抛出了一个错误:_pickle.PicklingError:无法序列化对象:异常:似乎您正试图从广播变量、操作或转换引用SparkContext。SparkContext只能在驱动程序上使用,不能在工作程序上运行的代码中使用

那么,有没有办法在foreach中使用SparkSession

编辑#1:
foreach中传递的函数示例如下:

def过程_数据(行):
df=spark.createDataFrame([行])
df.write.mode(“覆盖”).saveAsTable(“T2”)
spark.sql(“”)
合并到T1
在T2.type=“OrderReplace”和T1.ReferenceNumber=T2.originalReferenceNumber上使用T2
当匹配时
更新集
股份=T2.0股,
价格=T2.价格,
ReferenceNumber=T2.newReferenceNumber
""")

因此,我这里需要SparkSession,这在foreach中是不可用的。

从您希望在流数据集中逐行执行的任务的描述中,您可以尝试使用

一个流数据集可能有数千到数百万条记录,如果您在每条记录上点击外部系统,这将是一个巨大的开销。从您的示例来看,您似乎正在根据
T2
中的事件更新基本数据集
T1

通过上面的链接,您可以执行以下操作:

def process_data(df, epoch_id):    
  df.write.mode("overwrite").saveAsTable("T2")
  spark.sql("""
    MERGE INTO T1
    USING T2 ON T2.type="OrderReplace" AND T1.ReferenceNumber=T2.originalReferenceNumber
    WHEN MATCHED THEN
    UPDATE SET
      shares = T2.shares,
      price = T2.price,
      ReferenceNumber = T2.newReferenceNumber
  """)

streamingDF.writeStream.foreachBatch(process_data).start()   
关于你正在做的事情,还有一些额外的要点

  • 您正在尝试对流数据集执行foreach并覆盖
    T2
    hive表。由于记录是在集群管理器(如
    warn
    )中并行处理的,因此可能存在损坏的T2,因为多个任务可能会更新它
  • 如果要在T2中持久化记录(即使是暂时的),为什么不尝试将合并/更新逻辑作为一个单独的批处理过程?这将类似于我上面写的
    foreachBatch
    解决方案
  • 更新/创建HIVE表,最终映射一个映射/减少作业,这需要资源协商等。如果在每个记录上完成,可能会非常缓慢,例如,您可能需要考虑不同类型的目标,例如基于JDBC的目标。
    您只能在驱动程序中访问Spark会话。但在几乎每种情况下,都可以找到一种解决方案,以另一种方式运行所需的计算在我的情况下,我有流式数据,在这些数据上,我想运行foreach循环,以便逐行获取数据,然后对每行单独执行一系列操作,这些操作需要SparkSession。但是我发现foreach中的代码是在worker节点上运行的,因此无法访问那里的SparkSession…那么我在这里应该做什么呢?您应该尝试描述要在每一行上执行的操作。我需要根据这一行更新另一个表(比如T1)。因此,基本上,我正在为这一行创建一个spark数据帧,然后将该数据帧保存为表(比如T2),然后希望运行SQL查询(插入/删除/合并到等),该查询将根据T2中的数据更新T1。foreach中传递的函数示例如下:
    def process_data(row):df=spark.createDataFrame([row])df.write.mode(“overwrite”).saveAsTable(“T2”)spark.sql(“使用T2上的T2.type=“OrderReplace”和T1.ReferenceNumber=T2.originalReferenceNumber合并到T1中,匹配后更新集shares=T2.shares,price=T2.price,ReferenceNumber=T2.newReferenceNumber”“)
    因此,我需要在这里使用SparkSession,这在foreach中是不可用的。谢谢您的回答。但是foreachBatch的问题是,如果我有多个源行与同一目标行匹配,那么它会在合并操作中抛出错误