我是Spark Streaming的新手。我需要使用来自动态数据集的数据来丰富来自流的事件。我在创建动态数据集时遇到问题。此数据集应由来自不同流的数据摄取(但此流的吞吐量将远低于主要事件流)。另外,数据集的大小约为1-3 GB,因此使用简单的HashMap是不够的(在我看来)。
在Spark Streaming Programming Guide中我找到了:
val dataset: RDD[String, String] = ...
val windowedStream = stream.window(Seconds(20))...
val joinedStream = windowedStream.transform { rdd => rdd.join(dataset) }
和解释:“实际上,您还可以动态更改要加入的数据集。”这部分我根本不了解RDD如何动态更改?这不是一成不变的吗?
下面你可以看到我的代码。关键是要将每个新的RDD从myStream添加到myDataset,但显然这不会像我希望的那样工作。
val ssc = new StreamingContext(conf, Seconds(5))
val myDataset: RDD[String] = ssc.sparkContext.emptyRDD[String]
val myStream = ssc.socketTextStream("localhost", 9997)
lines7.foreachRDD(rdd => {myDataset.union(rdd)})
myDataset.foreach(println)
我将不胜感激任何帮助或建议。 此致!
答案 0 :(得分:2)
是的,RDD是不可变的。代码的一个问题是union()
返回一个新的RDD,它不会改变现有的myDataset
RDD。
编程指南说明如下:
实际上,您还可以动态更改要加入的数据集 反对。每批都会评估提供给
transform
的功能 间隔因此将使用dataset
的当前数据集 参考点。
第一句可能更好地解读如下:
实际上,您还可以动态更改要加入的哪个数据集 反对。
因此我们可以更改dataset
引用的RDD,但不能更改RDD本身。这是一个如何工作的例子(使用Python):
# Run as follows:
# $ spark-submit ./match_ips_streaming_simple.py.py 2> err
# In another window run:
# $ nc -lk 9999
# Then enter IP addresses separated by spaces into the nc window
from pyspark import SparkContext
from pyspark.streaming import StreamingContext
import time
BATCH_INTERVAL = 2
SLEEP_INTERVAL = 8
sc = SparkContext("local[*]", "IP-Matcher")
ssc = StreamingContext(sc, BATCH_INTERVAL)
ips_rdd = sc.parallelize(set())
lines_ds = ssc.socketTextStream("localhost", 9999)
# split each line into IPs
ips_ds = lines_ds.flatMap(lambda line: line.split(" "))
pairs_ds = ips_ds.map(lambda ip: (ip, 1))
# join with the IPs RDD
matches_ds = pairs_ds.transform(lambda rdd: rdd.join(ips_rdd))
matches_ds.pprint()
ssc.start()
# alternate between two sets of IP addresses for the RDD
IP_FILES = ('ip_file1.txt', 'ip_file2.txt')
file_index = 0
while True:
with open(IP_FILES[file_index]) as f:
ips = f.read().splitlines()
ips_rdd = sc.parallelize(ips).map(lambda ip: (ip, 1))
print "using", IP_FILES[file_index]
file_index = (file_index + 1) % len(IP_FILES)
time.sleep(SLEEP_INTERVAL)
#ssc.awaitTermination()
在while
循环中,我更改ips_rdd
每8秒引用一次的RDD。 join()
转换将使用ips_rdd
当前引用的任何RDD。
$ cat ip_file1.txt
1.2.3.4
10.20.30.40
$ cat ip_file2.txt
5.6.7.8
50.60.70.80
$ spark-submit ./match_ips_streaming_simple.py 2> err
using ip_file1.txt
-------------------------------------------
Time: 2015-09-09 17:18:20
-------------------------------------------
-------------------------------------------
Time: 2015-09-09 17:18:22
-------------------------------------------
-------------------------------------------
Time: 2015-09-09 17:18:24
-------------------------------------------
('1.2.3.4', (1, 1))
('10.20.30.40', (1, 1))
using ip_file2.txt
-------------------------------------------
Time: 2015-09-09 17:18:26
-------------------------------------------
-------------------------------------------
Time: 2015-09-09 17:18:28
-------------------------------------------
('50.60.70.80', (1, 1))
('5.6.7.8', (1, 1))
...
当上述作业正在运行时,在另一个窗口中:
$ nc -lk 9999
1.2.3.4 50.60.70.80 10.20.30.40 5.6.7.8
<... wait for the other RDD to load ...>
1.2.3.4 50.60.70.80 10.20.30.40 5.6.7.8