Apache spark 如何从工作人员访问SparkSession?
我在databricks中使用spark结构化流媒体。在这里,我使用foreach操作对每个数据记录执行一些操作。但是我传递给foreach的函数使用了SparkSession,但它抛出了一个错误:_pickle.PicklingError:无法序列化对象:异常:似乎您正试图从广播变量、操作或转换引用SparkContext。SparkContext只能在驱动程序上使用,不能在工作程序上运行的代码中使用 那么,有没有办法在foreach中使用SparkSession 编辑#1: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中
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()
关于你正在做的事情,还有一些额外的要点
T2
hive表。由于记录是在集群管理器(如warn
)中并行处理的,因此可能存在损坏的T2,因为多个任务可能会更新它foreachBatch
解决方案您只能在驱动程序中访问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的问题是,如果我有多个源行与同一目标行匹配,那么它会在合并操作中抛出错误