这是《Python大数据处理库 PySpark实战》一书的总结归纳
大数据时代
- 大数据的特点:大量、高速、多样、低价值密度、真实性
- 谷歌三篇论文是大数据的基石:Google File System 、Google MapReduce、Google Bi 个Table,解决存储、计算、查询的问题
分析工具
- Hadoop:HDFS存储、MapReduce计算、YARN资源调度,离线,不适合随机读写的在线事务处理模型
- Hive:把结构化的文件映射为数据表,可以用来查询数据,把SQL翻译成MR,不适合用于联机事务处理和实时查询,适用于大量不可变数据的批处理
- HBase:分布式、面向列的开源数据库,适合存储非结构化数据,适合写入量大读数据小的应用,查询简单的应用,对性能和可靠性要求较高的应用,内部使用LSTM树模型,读取任意数量的记录不会引发额外的寻道开销
- Spark:任务中间输出结果保存在内存中,适用于机器学习等需要迭代的算法,用Scala开发和可和Java一起使用,计算速度快,提供80多个高级运算符(转换、聚合),有很多对应组件(Spark SQL、Spark Streaming等),支持多种资源管理器(YARN、Standalone)
- Flink:计算框架和分布式处理引擎,对无界和有界数据流进行有状态计算,基于流执行引擎,DataSet API:对静态数据进行批处理操作;DataStream API:对数据流进行流处理操作;Table API:对结构化数据进行操作
- Druid:分布式支持实时多维OLAP分析的数据处理系统,支持数据实时处理和多维度数据分析查询,支持根据时间戳对数据进行预聚合摄入和聚合分析,对时序数据处理,支持较高并发,实时导入,导入即可被查询,采用分布式shared-nothing架构,可扩展到PB级,数据查询支持SQL。
- Kafka:为处理实时数据提供一个统一、高通量、低等待的平台。用于:发布和订阅(消息系统,读写流式数据),流数据处理,数据存储。可以作为连接各个子系统的数据管道,从而构建实时的数据管道和流式应用
- Elasticsearch:开源的分布式的,提供Restful API的搜索和数据分析引擎,底层是Apache Lucene,用Java开发,用Lucence做索引和搜索,全文索引,适用于实时文档存储和分析搜索引擎,能横向扩展支持PB级别的数据,可以用Kibana实现数据可视化分析
Spark
- 用户提交的任务为Application,一个App对应一个SparkContext,一个APP中存在多个Job,每触发一次Action操作就会产生一个Job(可串行也可并行),每个Job中有多个Stage,每个Stage有多个Task,由TaskScheduler发到各个Executor中执行,Executor和Application一样没有Job运行也存在的。每个Job可包含多个RDD转换算子,调度时可以生成多个Stage
核心组件
- Spark Core:包含任务调度、内存管路和容错机制,内部定义RDD(弹性分布式数据集)
- Spark SQL:处理结构化数据的查询分析
- Spark Streaming:实时数据流处理组件,需要配合消息队列Kafka
- Spark Mllib:包含通用机器学习功能的包
- Spark GraphX:处理图的库,如社交网络图的计算
重要概念
-
Application:提交一个作业就是一个Application,一个App对应一个SparkContext
-
Driver程序:Spark作业运行时会启动Driver进程,负责解析、生成Stage和调度Task到Executor执行,运行main函数并创建SparkContext
-
Cluster Manager:资源管理器 Standalone模式或者额yarn
-
Executor:真正执行作业Task的地方,接受Driver命令家在和运行Task,一个Executor执行一个到多个Task,多个Task之间可以相互通信
-
SparkContext:程序运行调度的核心,是Spark程序的入口, 由调度器DAGScheduler划分程序各个阶段,划分Stage,生成程序运行的有向无环图;调度器TaskSchedyker划分每个阶段的具体任务,Task的调度和容错;SchedulerBanked管理正在运行的程序分配计算资源的Exector
-
Job:工作单元,每触发一次Action操作就会产生一个Job(可串行也可并行),每个Job中有多个Stage,每个Stage有多个Task,
-
Stage:用来计算中间结果的Tasksets(一组相关联的任务集),在Shuffle的时候产生,如果下一个Stage要用到上一个Stage的全部数据要等上一个全部执行完,有两种Stage:ShuffleMapStage和ResultStage(最后一个Stage),其他的都是前者。ShuffleMapStage会产生中间结果,Stage经常被不同Job共享,前提是Job重用了同一个RDD
-
Task:任务执行的工作单位,每个Task会被发送到一个Worker节点上,每个Task对应RDD的一个Partition
-
RDD:弹性分布式数据集,不可变的、Lazy级别的、粗粒度的数据集合,包含一个或多个数据分片
-
DAG:有向无环图,将一个计算任务按照计算规则分解为若干子任务,子任务根据逻辑关系构建成为有向无环图
-
算子:Transformation由DAGSchedular划分到pipline,Lazy级别;Action算子触发Job执行运算
-
窄依赖:父RDD的分区只对应一个子RDD的分区,如果子RDD只有部分分区数据损坏,只要从对应的父RDD重新计算即可
-
宽依赖:子RDD分区依赖父RDD的所有分区。损坏需要从所有父RDD重新计算,数据处理成本高,尽量避免
-
Lineage:每个RDD记录自己依赖的父RDD信息
部署模式
-
Local模式
-
本地采用多线程
-
./bin/spark-submit \ --class com.myspark.Job.WordCount \ --master local[*] \ /root/sparkjar/spark-demo-1.0.jar
-
-
Spark on YARN
-
yarn-cluster模式下,Driver运行在Application Master中,节点的选在由YARN调度,可关闭Client,计算结果不在Client上显示,不适合交互类型的作业
-
yarn-client模式下,Driver运行在Client端,和请求的YARN Container通信来调度工作,不可关闭Client,适合交互和调试
-
# yarn-cluster ./bin/spark-submit \ --class com.myspark.Job.WordCount \ --master yarn \ --deploy-mode cluster \ /root/sparkjar/spark-demo-1.0.jar # yarn-client ./bin/spark-submit \ --class com.myspark.Job.WordCount \ --master yarn \ --deploy-mode client \ /root/sparkjar/spark-demo-1.0.jar
-
-
Standalone模式
-
和Local类似,Standalone的分布式调度器是Spark提供的,集群是Standalone的话,每个机器上都要有Spark
-
./bin/spark-submit \ --class com.myspark.Job.WordCount \ -master spark://192.168.1.71:7077 \ -executor-memory 16G \ -total-executor-cores 16\ /root/sparkjar/spark-demo-1.0.jar
基本操作
- 常用的Transformation操作
- map: 接收一个处理函数并行处理源RDD中的每个元素,返回与源RDD元素一一对应的新RDD。
- fiter: 并行处理源RDD中的每个元素,接受一个函数,并根据定义的规则对RDO
中的每个元素进行过滤处理,返回处理结果为true的元素重新组成新的RDD。 - flatMap: flatMap是 map和flatten的组合操作,与map函数相似,不过map函数返回的新RDD包含的元素可能是嵌套类型。
- mapPartitions: 应用于RDD中的每个分区。mapPartitions函数接受的参数为一个函数,该函数的参数为每个分区的送代器,返回值为每个分区元素处理之后组成的新的迭代器,该函数会作用于分区中的每一个元素。
- mapPartitionsWithIndex:作用与mapPartitions函数相同,只是接受的参数(一个函数),需要传入两个参数,分区的索引作为第一一个参数传入,按照分区的索引对分区中元素进行处理。
- Union:将两个RDD进行合并,返回结果为RDD中元素(不去重)。
- Intersection:对两个RDD进行取交集运算,返回结果为RDD无重复元素。
- Distinct:对RDD中元素去重。
- groupByKey:在健值对(K-V)类型的RDD中按Key分组,将相同Key的无素聚集到同一个分区内,此函数不能接受函数作为参数,只接受一个可选参数,即任务数。
- reduceByKey:对K-V类型的RDD按Key分组,它接受两个参数,第一个参数为处理函数,第二个参数为可选参数,用于设置reduce的任务数。reduceByKey函数能够在RDD分区本地提前进行聚合运算,这有效减少了shuffle过程传输的数量groupByKey函数更简洁高效。
- aggregateByKey:对K-V 类型的RDD按Key分组进行reduce计算,可接受三个参数,第一个是初始化值,第二个是分区内处理函数,第三个是分区间处理函数
- sortByKey: 对K-V类型的RDD内部元素按照Key进行排序,排序过程会涉及Shuffle操作。
- join: 对K-V类型的RDD进行关联操作,它只能处理两个RDD之间的关联,超过两个RDD关联需要多次使用join函数。另外,join操作只会关联出具有相同Key的元素,相
当于SQL语句中的inner join。 - cogroup:对K-V类型的RDD进行关联,cogroup在 处理多个RDD的关联上比join更加优雅,它可以同时传入多个RDD作为参数进行关联。
- coalesce:对RDD重新分区,将RDD中的分区数减小到参数numPartitions个,不会产生shufle。在较大的数据集中使用filer等过滤操作后可能会产生多个大小不等的中间结果数据文件,重新分区并减小分区可以提高作业的执行效率,是Spark中常用一种优化手段。
- repartition:对RDD重新分区,接受一个参数,即numPartitions分区数,它是coalesce函数设置shuffle为true的一种实现形式。
- 常用的Action操作
- reduce:处理RDD两两之间元素的聚集操作。
- collct:返回RDD中所有数据元素。
- Count:返回RDD中元素个数。
- First:返回RDD中的第一个元素。
- Take:返回RDD中的前N个元素。
- saveAsTextFile:将RDD写入文本文件,保存至本地文件系统或者HDFS中。
- saveAsSequnceFile:将KV类型的RDD写入Sequence File文件, 保存至本地文件系统或者HDFS中。
- countByKey: 返回K.V类型的RDD.这个RDD中数据为每个Key包含的元素个数。
- Foreach:遍历RDD中所有元素, 接受参数为一个函教,常用操作是传入println函教打印所有元素。
- 可以使用persist() 或者 cache() 方法缓存RDD ,unpersist()消除缓存
- MEMORY_ONLY: RDD仅缓仔一份到内仔,此为默认致。
- MEMORY_ONLY_2:将RDD分别缓存在集群的两个节点上,RDD在集群内存中保存
两份。 - MEMORY_ONLY_SER:将RDD以Java序列化对象的方式缓存到内存中,有效减少了
RDD在内存中占用的空间,不过读取时会消耗更多的CPU资源。 - DISK_ONLY: RDD仅缓存一份到磁盘。
- MEMORY_ AND_DISK: RDD仅缓存一份到内存,当内存中空间不足时,会将部分
RDD分区缓存到磁盘。 - MEMORY_AN_ DISK 2:将RDD分别缓存在集群的两个节点上,当内存中空间不足
时,会将部分RDD分区缓存到磁盘,RDD在集群内存中保存两份。 - MEMORY_AND_DISK_SER:将RDD2Java序列化对象的方式缓存到内存中,当内存
中空间不足时,会将部分RDD分区缓存到磁盘,有效减少了RDD在内存中占用6信
间,不过读取时会消耗更多的CPU资源。 - OFF_HEAP:将RDD以序列化的方式缓存到JVM之外的存储空间中,
与其他缓存模式相比,减少了JVM垃圾回收开销。