PySpark是Apache Spark支持python编写的工具,python简单实用,使用python操作spark做简单的数据分析处理也是一种选择。Cassandra是分布式NoSQL数据库系统,可以简单理解它和HBase和MongoDB类似。本文主要分享PySpark实际应用和通过PySpark操作Cassandra遇到的坑。
首先根据spark、cassandra版本选择connector版本,参考链接:
[https://github.com/datastax/spark-cassandra-connector]
添加connector,可以在提交任务中添加:
./bin/pyspark --packages com.datastax.spark:spark-cassandra-connector_2.11:2.4.2
也可以在python脚本中添加:
os.environ["PYSPARK_SUBMIT_ARGS"] = '--packages com.datastax.spark:spark-cassandra-connector_2
Python版本问题首先是一个坑。
如果写代码用的python3,但是master和worker上默认python2,此时会报python运行的错误。对于用java和scala,spark-submit上传打好的jar包即可提交执行,因为driver和executor都是以JVM为载体来运行和执行任务。而对于PySpark,Spark是在外围包装一层Python API,借助Py4j实现Python和Java的交互。
因此,如果提交的脚本python版本是3,需要在master和worker节点安装python3,并在python脚本中配置节点的python路径:
os.environ["PYSPARK_PYTHON"] = '/bin/python3'
os.environ["PYSPARK_DRIVER_PYTHON"] = '/bin/python3'
此处的python路径,是master和worker节点的python路径,与上传spark任务的机器中的python路径无关。
比较推荐的是应用sparksql中的sparksession对象,创建spark dataset或spark dataframe。
样例如下:
from pyspark.sql import SparkSession
spark = SparkSession.builder.appName(sys.argv[0])\
.config("spark.cassandra.connection.host", "cassandra_host_ip").getOrCreate()
# 加载Cassandra数据到dataframe
df = spark.read.format("org.apache.spark.sql.cassandra")\
.options(table="table_name", keyspace="keyspace_name").load()
# UDF
from pyspark.sql.functions import udf
class UdfSample(object):
......
udf1 = udf(lambda z: UdfSample(z)......, StringType())
# dataframe写入Cassandra
df.write.format("org.apache.spark.sql.cassandra")\
.options(table="table_name ", keyspace="keyspace_name")\
.mode('append').save()
Dataframe中特别多的会应用udf和lambda。对于自定义udf,序列化、反序列化、及通信IO性能损耗比较明显,而Spark sql中内置的udf会降低数据在executor jvm和python worker之间序列化反序列化、通信等损耗。
spark dataframe和pandas dataframe是两种不同的数据格式,虽然有方法实现两者相互转化,但是实用性不大,且浪费资源。
使用spark-submit提交python脚本到spark集群,例如
./bin/spark-submit --master spark://ip:port ./python1.py
同样的命令手动输入运行没问题,但是在crontab上无法执行。
问题本质和crontab无关,这也是python环境的问题。如果在python脚本中加入打印sys.path的代码,会发现手动执行和crontab执行的sys.path中python路径不同。简单直接的方法是在提交命令中加入本地的python运行路径。
./bin/spark-submit
--master spark://ip:port
--conf spark.pyspark.python=/bin/python
--conf spark.pyspark.driver.python=/bin/python
./python1.py
对于简单离线任务,可以使用PySpark快速部署提交,简单方便。但在大数据情景中,JVM和Python进程间频繁通信会导致性能损耗,尽量慎用PySpark。后续实际中遇到问题,也会继续补充。