手写spark wordCount
搭建wordCount项目:
https://blog.csdn.net/py_123456/article/details/82665623
1、代码:
val conf: SparkConf = new SparkConf().setMaster(Local[*]).setAppName("wordCount")
val sc=new SparkContext(conf)
sc.textFile("/input").flatMap(" ").map((_,1)).reduceByKey(_+_).saveAsTextFile("/output")
sc.stop
val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("WordCount")
val sc = new SparkContext(conf)
sc.textFile("/input")
.flatMap(_.split(" "))
.map((_, 1))
.reduceByKey(_ + _)
.saveAsTextFile("/output")
sc.stop()
2、详解:
//下面是通过Spark上下文调用textFile函数创建一个包装好底层数据集的RDD对象:
//这里没有指定前缀hdfs://YunMaster01:9000,但是SparkContext(Spark上下文,即sc对象)中已经封装了这些默认的配置信息,即创建Spark上下文对象时就已经封装了这些上下文配置信息(包括操作的底层数据源,如这里的HDFS);这里最好不要加上hdfs前缀,因为加上了之后代码就被编译后固化了,造成不可配置,如果不加则SparkContext可以基于配置来自动选择(数据源类型可以通过配置来改变),提升高可维护性。
scala>val dataSet=sc.textFile("/spark/input")
//SparkContext调用textFile函数将返回一个org.apache.spark.rdd.RDD[String]类型的对象(RDD在Spark的架构源码中被Scala定义为一个接口(trait)类型;方括号中的String表示RDD集合中的元素类型为字符串类型);此RDD的具体实现是MapPartitionRDD(即:字典分区RDD);textFile操作仅仅是执行数据抽象,并没有立即执行数据的读取(read)操作,数据的读取操作会延迟到执行action动作时才发生;因此textFile函数属于一种transformation动作,transformation动作是lazy级别的操作。
//查看数据源的输入路径(如果数据源使用HDFS则显示为HDFS路径),以下如不特别加以说明默认都是基于HDFS的数据源(因为这个最常用)
//toDebugString函数会根据数据集的来源路径(RDD依赖)进行反向推理并从上到下依次显示RDD路径源列表
scala>dataSet.toDebugString()
//返回数据集中的记录数量,这会启动一个action(textFile函数是一种转换(transformation),不会启动action);action是指Spark会在底层启动作业(Job)或任务(Task)的计算操作;而转换(transformation)仅仅是实现数据的封装和抽象(只涉及到数据在节点本地上的抽象读(注意:没有真正意义上的读,因为没有产生任何IO操作),但是数据的写操作则属于action操作,因为它涉及到IO操作过程,比如:saveAsTextFile函数)
scala>dataSet.count
//Spark中的一个分区(partition)相当于HDFS中的一个块(Block),即Spark中一个partition的尺寸等于一个HDFS文件块的尺寸(BlockSize=128M)
//下面调用flatMap函数处理dataSet集合中的每一行,此函数调用完成之后又将产生一个新的RDD对象结果集,实际上所有的Spark操作都是基于RDD集合对象的操作(一切皆为RDD操作)
scala>val dataSet02=dataSet.flatMap(_.split(" "))
//实现第二次映射操作产生新的RDD集合对象
scala>val dataSet03=dataSet02.map(word=>(word,1))
//上面的两个map算子相当于MapReduce中的map方法的操作;而下面与reduce相关的算子则相当于MapReduce中的reduce方法的操作
//由于reduce操作涉及到在节点之间转移和重新分配数据,因此此过程涉及到shuffle机制,执行reduce操作过程中产生的shuffle是为了归并相同Key的记录到同一分组以执行SQL概念中的分组统计
scala>val dataSet04=dataSet03.reduceByKey(_+_)
//从上面的执行过程来看,Spark的底层计算原理与Hadoop的底层计算原理是类同的,只是Spark在此基础上引入了RDD的概念,将一切的操作归入集合RDD的操作(实际上,Hadoop中MapReduce操作本身就是针对集合对象进行操作,只不过Hadoop没有抽象出这样一个概念而已),由于引入了RDD的概念,所以Spark可以将一切操作(应用的所有操作步骤)的输入源和输出源都抽象为RDD对象的操作,这样以来,各个操作之间就可以通过RDD对象链接成操作链(上一个操作的输出源是一个RDD对象,该RDD对象可以直接作为下一个操作的输入源)
//将应用执行过程中处理后的数据最终存储到HDFS文件系统中去(此过程是action操作)
scala>dataSet04.saveAsTextFile("/spark/output")
3、WordCount计算原理:
A、textFile函数:返回一个HadoopRDD,HadoopRDD在执行action操作计算数据时会将数据从分布式磁盘读取到分布式内存中,即从worker节点的本地磁盘读取到worker节点的本地内存中,RDD更多的是指分布式内存存储,一种数据的逻辑存储系统;
HadoopRDD产生的是一个元组集合(即集合中的每个元素是一个元组类型),元组的第一个元素是行记录的索引(Key,字节偏移量),元组的第二个元素是行记录内容本身(Value);
基于HadoopRDD会继续产生一个字符串集合MapPartitionRDD,此集合中的每个字符串代表行记录内容(没有行记录的索引,丢弃了字节偏移量Key)
B、flatMap函数:此函数仍然产生一个字符串MapPartitionRDD集合
C、map函数:此函数产生一个二元素元组类型的MapPartitionRDD集合
D、reduceByKey函数:基于相同Key的Value进行统计;先进行本地统计(执行卡宾函数统计可以减少数据传送量,降低网络负载),再进行集群模式统计(shuffle);本地统计之后的结果会根据分区策略将统计后的基于二元素元组的MapPartitionRDD集合数据写出到不同的本地文件中;在数据被传送到另一个节点之前的所有操作都是在同一个节点上的操作;在此,于同一个节点上的所有操作都是在同一个Stage中;同一个Stage中的所有操作都是基于内存的链式迭代操作(你也可以在这个迭代过程中手动缓存中间结果);我们通常说Spark是基于内存迭代的,其缘由就在于此。
E、shuffle是整个分布式计算的性能瓶颈所在,shuffle过程是从一个节点将数据传送到另一个节点的过程(即便在同一个节点上也是切换到另一个JVM进程来处理),这个过程中会针对每一份数据至少产生两次IO(本次磁盘IO、网络IO);shuffle过程是依据数据分区策略来进行的,shuffle之后将从一个Stage阶段过渡到另一个新的Stage阶段,shuffle之后将在另一个新的Stage阶段产生一个基于二元素元组的ShuffledRDD集合。
F、saveAsTextFile函数:将ShuffledRDD集合转换为MapPartitionRDD(实际上就是追加一个字节偏移量Key将每一个元组再包装成一个二元素元组(第一个元素是字节偏移量Key)),然后将其写出到HDFS文件系统中去。
参考博客:https://www.cnblogs.com/mmzs/p/8241500.html
手写spark wordCount的更多相关文章
- 如何用卷积神经网络CNN识别手写数字集?
前几天用CNN识别手写数字集,后来看到kaggle上有一个比赛是识别手写数字集的,已经进行了一年多了,目前有1179个有效提交,最高的是100%,我做了一下,用keras做的,一开始用最简单的MLP, ...
- 第三篇:基于K-近邻分类算法的手写识别系统
前言 本文将继续讲解K-近邻算法的项目实例 - 手写识别系统. 该系统在获取用户的手写输入后,判断用户写的是什么. 为了突出核心,简化细节,本示例系统中的输入为32x32矩阵,分类结果也均为数字.但对 ...
- 手写一个简单的ElasticSearch SQL转换器(一)
一.前言 之前有个需求,是使ElasticSearch支持使用SQL进行简单查询,较新版本的ES已经支持该特性(不过貌似还是实验性质的?) ,而且git上也有elasticsearch-sql 插件, ...
- Hive手写SQL案例
1-请详细描述将一个有结构的文本文件student.txt导入到一个hive表中的步骤,及其关键字 假设student.txt 有以下几列:id,name,gender三列 1-创建数据库 creat ...
- 【Win 10 应用开发】手写识别
记得前面(忘了是哪天写的,反正是前些天,请用力点击这里观看)老周讲了一个14393新增的控件,可以很轻松地结合InkCanvas来完成涂鸦.其实,InkCanvas除了涂鸦外,另一个大用途是墨迹识别, ...
- JS / Egret 单笔手写识别、手势识别
UnistrokeRecognizer 单笔手写识别.手势识别 UnistrokeRecognizer : https://github.com/RichLiu1023/UnistrokeRecogn ...
- 【转】机器学习教程 十四-利用tensorflow做手写数字识别
模式识别领域应用机器学习的场景非常多,手写识别就是其中一种,最简单的数字识别是一个多类分类问题,我们借这个多类分类问题来介绍一下google最新开源的tensorflow框架,后面深度学习的内容都会基 ...
- caffe_手写数字识别Lenet模型理解
这两天看了Lenet的模型理解,很简单的手写数字CNN网络,90年代美国用它来识别钞票,准确率还是很高的,所以它也是一个很经典的模型.而且学习这个模型也有助于我们理解更大的网络比如Imagenet等等 ...
- 使用神经网络来识别手写数字【译】(三)- 用Python代码实现
实现我们分类数字的网络 好,让我们使用随机梯度下降和 MNIST训练数据来写一个程序来学习怎样识别手写数字. 我们用Python (2.7) 来实现.只有 74 行代码!我们需要的第一个东西是 MNI ...
随机推荐
- LPAT: Learning to Predict Adaptive Threshold for Weakly-supervised Temporal Action Localization [Paper Reading]
Motivation: 阈值分割的阈值并没有通过模型训练学出来,而是凭借主观经验设置,本文通过与背景得分比较提取对应的proposal,不用阈值的另一篇文章是Shou Zheng的AutoLoc,通过 ...
- C语言知识点总结篇
Debug和Release版本比较 Debug附加了许多调试信息,主要用于调试,故文件大: Release是经过优化后的版本,去掉了调试信息,代码进行了优化,故文件较小,且编译速度快过Debug,用于 ...
- .netcore docker noe4j
1.借用docker搭建noe4j环境 docker pull neo4j docker run -d --restart=always -p7474: -p7687: -v /root/docker ...
- TServerSocket组件
主要作为服务器端的套接字管理器使用.它封装了服务器端的套接字.在打开套接字后,服务器端就处于监听状态,在接收到其它机器的连接请求后,与客户端建立连接,创建一个新的套接字,用于和客户端互传数据,此时TS ...
- 【8】学习C++之this指针
在学习类的时候,我们可以考虑到一种情况: class Array { public: Array(int len); ~Array(); void setLen(int len) { len=len; ...
- php调用webservice接口,java代码接收不到参数
前段时间做了一个项目的二次开发,有个功能是需要php调用java实现的webservice接口,并传递一些参数给接口,然后按照对方提供的接口说明文档进行传参调用,java那边有接收到请求,但是参数总是 ...
- Django--视图函数
目录 视图函数 HttpRequest对象 request属性 request常用方法 HttpResponse对象 render() redirect() JsonResponse 视图函数 一个视 ...
- 2019-08-01 jquery中常用方法
1.attr()方法设置或返回被选元素的属性值 <html> <meta charset="utf-8"/> <head><title&g ...
- 22、vue实现随机四位数验证码
效果图: 1.新建生成验证码的组件Sidentify.vue(代码如下): <template> <div class="s-canvas"> <ca ...
- [转]C++类成员修饰const和mutable
const:常量,不变的 mutable:易变的 从意思上理解,可见const和mutable是一对反义词,它们都是C++的关键字. const成员函数不能修改调用它的对象.类的成员函数可以被声明为c ...