手写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 ...
随机推荐
- jmeter通过BeanShell,实现对接口参数HmacSHA256加密(转)
jmeter通过BeanShell,实现对接口参数HmacSHA256加密2019-04-29 05:10 ps. 最近抓包网站的登陆请求,发现就2个参数,用户名和密码,通过工具去请求这个接口,一直返 ...
- 13. Scala函数式编程(高级部分)
13.1 偏函数(partial function) 13.1.1 需求 -> 思考 一个集合val list = List(1,2,3,4,"abc"),完成如下要求 1) ...
- 类、闭包、monand
类.闭包.monand 三者的相同点都是封装了数据与操作. 类:定义数据类型,倾向于数据的抽象:集合数据为操作提供上下文. 闭包:对环境变量和操作的封装抽象.操作基于环境变量,核心问题是环境变量的管理 ...
- Docker安装Consul集群
Docker 安装Consul集群 使用windows 环境,Docker desktop community 构建consul集群. 1.docker 容器网络 docker安装后,默认会创建三种网 ...
- vuejs应用开发前后端分离
我们知道,无论是web应用还是app应用都有一个前后端,前端主要负责界面交互,后端负责数据持久化.在正规公司中一般是由两个团队来分别完成前端和后端的开发,在小公司或者个人开发的项目中,前后端很有可能是 ...
- js获取某月有多少天
var day = new Date(2018,10,0); //最后一个参数为0,意为获取2018年10月一共多少天 console.log(day.getDate());
- Java 流程控制语句 之 顺序结构
在一个程序执行的过程中,各条语句的执行顺序对程序的结果是有直接影响的.也就是说,程序的流程对运行结果 有直接的影响.所以,我们必须清楚每条语句的执行流程.而且,很多时候我们要通过控制语句的执行顺序来实 ...
- JS案例 - 城市三级联动
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Ajax跨域问题及解决方案 asp.net core 系列之允许跨越访问(Enable Cross-Origin Requests:CORS) c#中的Cache缓存技术 C#中的Cookie C#串口扫描枪的简单实现 c#Socket服务器与客户端的开发(2)
Ajax跨域问题及解决方案 目录 复现Ajax跨域问题 Ajax跨域介绍 Ajax跨域解决方案 一. 在服务端添加响应头Access-Control-Allow-Origin 二. 使用JSONP ...
- 【爬虫】使用selenium设置cookie
https://segmentfault.com/a/1190000015826749