Apache spark 在带有kafka流的pyspark中,将以前的数据与当前数据一起使用的方法
我正在从我的制作人发送dict对象,并使用pyspark创建一个新对象。但我想要形成的对象类型也需要先前数据的键、值对。我尝试过窗口批处理和reduceByKey,但它们似乎都不起作用 假设我的producer对象类似于“url\u id”和“url”对的列表。例如,{“url_id”:“google.com}和在spark中,我想形成一个对象,如:{“data”:{“url_id”:“url”,“url_id_of_previous_url”:“url”,…等等} 我的spark代码是:Apache spark 在带有kafka流的pyspark中,将以前的数据与当前数据一起使用的方法,apache-spark,pyspark,spark-structured-streaming,Apache Spark,Pyspark,Spark Structured Streaming,我正在从我的制作人发送dict对象,并使用pyspark创建一个新对象。但我想要形成的对象类型也需要先前数据的键、值对。我尝试过窗口批处理和reduceByKey,但它们似乎都不起作用 假设我的producer对象类似于“url\u id”和“url”对的列表。例如,{“url_id”:“google.com}和在spark中,我想形成一个对象,如:{“data”:{“url_id”:“url”,“url_id_of_previous_url”:“url”,…等等} 我的spark代码是: co
conf = SparkConf().setAppName(appName).setMaster("local[*]")
sc = SparkContext(conf=conf)
stream_context = StreamingContext(sparkContext=sc, batchDuration=batchTime)
kafka_stream = KafkaUtils.createDirectStream(ssc=stream_context, topics=[topic],
kafkaParams={"metadata.broker.list":"localhost:9092",
'auto.offset.reset':'smallest'})
lines = kafka_stream.map(lambda x: json.loads(x[1]))
在这之后我被卡住了。你能告诉我用spark是否可以形成这样的obj吗?如果可以的话,我应该用什么方法?据我所知,你可以用两种方法解决这个问题 第一种方法很简单,通过启用一些内部缓存,让消息生成应用程序本身发送这对消息(当前和以前) 第二种方法是使用Spark Stateful Streaming在Spark状态上下文中维护最后一条消息的值。由于您使用PySpark,我知道的唯一选项是使用启用检查点的
updateStateByKey
Pypark流的典型流量如下所示
- 定义初始值和更新函数的步骤
- 维护一个公共密钥以匹配当前和以前的消息,我在本例中使用了
pair\u msgs
# RDD with initial state (key, value) pairs initialStateRDD = sc.parallelize([(u'pair_msgs', '{"url_id":"none"}')]) def updateFunc(new_url_msg, last_url_msg): if not new_url_msg: return last_url_msg else: new_url_dict = json.loads(new_url_msg[0]) new_url_dict['url_id_previous'] = json.loads(last_url_msg)['url_id'] return json.dumps(new_url_msg)
- 要使用公共密钥映射输入消息,请在本例中使用
pair\msgs
# RDD with initial state (key, value) pairs
initialStateRDD = sc.parallelize([(u'pair_msgs', '{"url_id":"none"}')])
def updateFunc(new_url_msg, last_url_msg):
if not new_url_msg:
return last_url_msg
else:
new_url_dict = json.loads(new_url_msg[0])
new_url_dict['url_id_previous'] = json.loads(last_url_msg)['url_id']
return json.dumps(new_url_msg)
updateStateByKey
转换
feeds = kafka_stream.map(lambda x: x[1])
pair_feed = feeds.map(lambda feed_str: ('pair_msgs', feed_str)) \
.updateStateByKey(updateFunc, initialRDD=initialStateRDD)
[注意:据我所知,PySpark结构化流媒体尚未获得有状态流媒体支持,因此我相信上述示例仍然有意义]据我所知,您可以通过两种方式解决此问题 第一种方法很简单,通过启用一些内部缓存,让消息生成应用程序本身发送这对消息(当前和以前) 第二种方法是使用Spark Stateful Streaming在Spark状态上下文中维护最后一条消息的值。由于您使用PySpark,我知道的唯一选项是使用启用检查点的
updateStateByKey
Pypark流的典型流量如下所示
- 定义初始值和更新函数的步骤
- 维护一个公共密钥以匹配当前和以前的消息,我在本例中使用了
pair\u msgs
# RDD with initial state (key, value) pairs initialStateRDD = sc.parallelize([(u'pair_msgs', '{"url_id":"none"}')]) def updateFunc(new_url_msg, last_url_msg): if not new_url_msg: return last_url_msg else: new_url_dict = json.loads(new_url_msg[0]) new_url_dict['url_id_previous'] = json.loads(last_url_msg)['url_id'] return json.dumps(new_url_msg)
- 要使用公共密钥映射输入消息,请在本例中使用
pair\msgs
# RDD with initial state (key, value) pairs
initialStateRDD = sc.parallelize([(u'pair_msgs', '{"url_id":"none"}')])
def updateFunc(new_url_msg, last_url_msg):
if not new_url_msg:
return last_url_msg
else:
new_url_dict = json.loads(new_url_msg[0])
new_url_dict['url_id_previous'] = json.loads(last_url_msg)['url_id']
return json.dumps(new_url_msg)
updateStateByKey
转换
feeds = kafka_stream.map(lambda x: x[1])
pair_feed = feeds.map(lambda feed_str: ('pair_msgs', feed_str)) \
.updateStateByKey(updateFunc, initialRDD=initialStateRDD)