Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Apache spark Databricks激发了将结构化流写入许多接收器的最佳实践?_Apache Spark_Pyspark_Apache Kafka_Databricks_Spark Structured Streaming - Fatal编程技术网

Apache spark Databricks激发了将结构化流写入许多接收器的最佳实践?

Apache spark Databricks激发了将结构化流写入许多接收器的最佳实践?,apache-spark,pyspark,apache-kafka,databricks,spark-structured-streaming,Apache Spark,Pyspark,Apache Kafka,Databricks,Spark Structured Streaming,我正在使用databricks spark 3.x,我正在读取大量流(100+),每个流都有自己的合约,需要写入到自己的delta/parquet/sql/anywhere表中。虽然这是很多流,但每个流的活动量很低-一些流可能一天只能看到数百条记录。我确实想流,因为我的目标是一个相当低的延迟方法 下面是我要说的(代码为了简单而缩写;我正确地使用了检查点、输出模式等)。 假设schemas变量包含每个主题的模式。我尝试过这种方法,在这里我创建了大量的单独流,但它需要大量的计算,而且大部分都被浪费了

我正在使用databricks spark 3.x,我正在读取大量流(100+),每个流都有自己的合约,需要写入到自己的delta/parquet/sql/anywhere表中。虽然这是很多流,但每个流的活动量很低-一些流可能一天只能看到数百条记录。我确实想流,因为我的目标是一个相当低的延迟方法

下面是我要说的(代码为了简单而缩写;我正确地使用了检查点、输出模式等)。 假设
schemas
变量包含每个主题的模式。我尝试过这种方法,在这里我创建了大量的单独流,但它需要大量的计算,而且大部分都被浪费了:

def batchprocessor(topic, schema):
  def F(df, batchId):
    sql = f'''
  MERGE INTO SOME TABLE
  USING SOME MERGE TABLE ON SOME CONDITION
  WHEN MATCHED
  UPDATE SET *
  WHEN NOT MATCHED
  INSERT *
  '''
    df.createOrReplaceTempView(f"SOME MERGE TABLE")
    df._jdf.sparkSession().sql(sql)
  return F
for topic in topics:
  query = (spark
    .readStream
    .format("delta")
    .load(f"/my-stream-one-table-per-topic/{topic}")
    .withColumn('json', from_json(col('value'),schemas[topic]))
    .select(col('json.*'))
    .writeStream
    .format("delta")
    .foreachBatch(batchProcessor(topic, schema))
    .start())
我还试图创建一个只进行大量过滤的流,但即使在我将一条消息推送到一个主题的测试环境中,性能也相当糟糕:

def batchprocessor(df, batchId):
  df.cache()
  for topic in topics:
    filteredDf = (df.filter(f"topic == '{topic}'")
      .withColumn('json', from_json(col('value'),schemas[topic]))
      .select(col('json.*')))
    sql = f'''
  MERGE INTO SOME TABLE
  USING SOME MERGE TABLE ON SOME CONDITION
  WHEN MATCHED
  UPDATE SET *
  WHEN NOT MATCHED
  INSERT *
  '''
    filteredDf.createOrReplaceTempView(f"SOME MERGE TABLE")
    filteredDf._jdf.sparkSession().sql(sql)
  df.unpersist()

query = (spark
.readStream
.format("delta")
.load(f"/my-stream-all-topics-in-one-but-partitioned")
.writeStream
.format("delta")
.foreachBatch(batchProcessor)
.start())

有没有什么好方法可以从本质上对这样的流进行多路分解?它已经分区了,所以我假设查询计划器没有做太多的冗余工作,但似乎仍然有大量的开销。

我运行了一系列基准测试,选项2更有效。我还不完全知道为什么

最终,性能仍然不是我想要的-每个主题都按顺序运行,无论大小,因此每个主题上的单个记录都会导致FIFO调度程序将许多效率非常低的小操作排队。我使用并行化解决了这个问题:

import threading
def writeTable(table, df, poolId, sc):
  sc.setLocalProperty("spark.scheduler.pool", poolId)
  df.write.mode('append').format('delta').saveAsTable(table)
  sc.setLocalProperty("spark.scheduler.pool", None)
def processBatch(df, batchId):
  df.cache()
  dfsToWrite = {}
  for row in df.select('table').distinct().collect():
    table = row.table
    filteredDf = df.filter(f"table = '{table}'")
    dfsToWrite[table] = filteredDf
  threads = []
  for table,df in dfsToWrite.items():
    threads.append(threading.Thread(target=writeTable,args=(table, df,table,spark.sparkContext)))
  for t in threads:
    t.start()
  for t in threads:
    t.join()
  df.unpersist()

卡夫卡的接触点是什么?我看到你在读和写delta lake…我在做一个两阶段的过程,从卡夫卡(119个主题)开始,写到delta lake,然后从delta lake(青铜/银/金建筑)开始。我尝试将所有主题写入一个分区表,并将每个主题写入其自己的表,因为这些主题对管道的这一阶段有不同的影响。您最终的解决方案是什么?我相信第二种解决方案可能更快,因为您没有多次读取卡夫卡的数据。我也有同样的问题,我对自己的表现非常失望。对于Spark来说,有很多慢流似乎是一个很大的开销。我认为造成这种差异的原因是驱动程序对每个流查询所做的开销——只有一个流查询可以最大限度地减少这种开销。不过,我对我的第二种方法并不完全满意,因为每个主题在完成之前都完全占用FIFO调度程序,因此每个主题只有一条消息的噩梦场景会产生一系列非常低效的线性写入。通过使用python线程和spark池在foreachbatch中实现真正的并行化,我最终获得了所需的性能。我用示例代码更新了我的答案感谢您的回复,当我写下我的第一条评论时,我觉得:无论如何,我注意到在您的解决方案中,您不再使用“合并到表中…”-这是否也会对您的性能产生负面影响?不利的一面是,你可能会得到重复的结果。您使用了多少个不同的池?是每个主题一个吗?我试图通过操纵spark_WORKER_CORES的值来调整spark,以获得每个核心更多的并发性,并在Scala中使用线程,但我对延迟和它所消耗的CPU量不感兴趣。这个解决方案确实对CPU造成了相当大的冲击,但在我的例子中(130多个主题,只有4-5个看到高使用率),它将延迟从约7分钟降低到了约20秒。我每个主题使用一个池。出于不相关的原因,我放弃了合并到表中,对不起,我只是在寻找我能找到的每一个优化,并确定“if matched”分支从未被击中。