使用动态数据集

时间:2015-05-21 14:16:30

标签: scala apache-spark spark-streaming rdd

我是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)

我将不胜感激任何帮助或建议。 此致!

1 个答案:

答案 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