我使用spark stream来传输来自Kafka的数据,我希望通过MySql中的数据来过滤数据。
例如,我从kafka获取数据,如:
{"id":1, "data":"abcdefg"}
并且MySql中有数据如下:
id | state
1 | "success"
我需要查询MySql以获取term id的状态。 我可以在filter的函数中定义一个到MySql的连接,它可以工作。像这样的代码:
def isSuccess(x):
id = x["id"]
sql = """
SELECT *
FROM Test
WHERE id = "{0}"
""".format(id)
conn = mysql_connection(......)
result = rdbi.query_one(sql)
if result == None:
return False
else:
return True
successRDD = rdd.filter(isSuccess)
但是它将为RDD的每一行定义连接,并且会浪费大量的计算资源。
过滤器怎么做?
答案 0 :(得分:1)
我建议您使用Apache Spark中的mapPartition
来防止为每个RDD初始化MySQL连接。
这是我创建的MySQL表:
create table test2(id varchar(10), state varchar(10));
使用以下值:
+------+---------+
| id | state |
+------+---------+
| 1 | success |
| 2 | stopped |
+------+---------+
使用以下PySpark代码作为参考:
import MySQLdb
data1=[["1", "afdasds"],["2","dfsdfada"],["3","dsfdsf"]] #sampe data, in your case streaming data
rdd = sc.parallelize(data1)
def func1(data1):
con = MySQLdb.connect(host="127.0.0.1", user="root", passwd="yourpassword", db="yourdb")
c=con.cursor()
c.execute("select * from test2;")
data=c.fetchall()
dict={}
for x in data:
dict[x[0]]=x[1]
list1=[]
for x in data1:
if x[0] in dict:
list1.append([x[0], x[1], dict[x[0]]])
else:
list1.append([x[0], x[1], "none"]) # i assign none if id in table and one received from streaming dont match
return iter(list1)
print rdd.mapPartitions(func1).filter(lambda x: "none" not in x[2]).collect()
我得到的输出是:
[['1', 'afdasds', 'success'], ['2', 'dfsdfada', 'stopped']]