这篇Blog将探讨Java IO流和Spark RDD之间的关系
Java IO流分为字节流和字符流,最简单的一种读取文件的方式如下图所示:
如上图所示,当FileInputStream读取文件之后,没有做保存就直接输出给控制台打印了,读取一个字节就输出一个字节,这是最简单的模式
但是这种字节流读文件的速度不够高效,所以又出现了BufferedInputStream,如下图所示:
在FileInputStream外面嵌套了一层BufferedInputStream,当FileInputStream读取一个字节之后并没有直接输出给控制台,而是到了BufferedInputStream提供的Buffer缓冲区,待Buffer满了之后,再一次性把缓冲区的字节都交给控制台输出
但这还是字节流啊,我们希望做一个字符流哎,读取一个字节,待能够拼接成一个字符再输出,所以又有了BufferedReader,他里面嵌套一个InputStreamReader,InputStreamReader里面又有一个FileInputStream,如下图所示:
FileInputStream读取字节之后先交给InputStreamReader,这里有个Buffer缓冲区,待这个Buffer能够组成一个字符的时候,再交给外层的BufferedReader,最后再把一个字符输出的控制台
从上面三种形式的IO流,我们可以发现为了做到某个功能,都是把简单的一些功能叠加在了一起,是一种装饰者设计模式,Spark RDD正是这种模式,接下来看一下Spark的WordCount是如何叠加RDD的
Spark 实现 WordCount的一种方式如下图所示:
首先使用textFile从文件里面按行读取数据,然后使用一个flatMap将这些个行按照空格分词,分词之后呢,使用Map将每个单词转换为(单词,1)的形式,紧接着下一步就是针对刚刚转换的数据,做一个groupBy的操作了,按照单词进行分组,分完组之后就是使用reduceByKey进行聚合操作,最后再使用collect进行收集,就得到了最终结果。本篇blog就不展示具体的代码了,读者可以点击这串字看一下Spark实现WordCount的三种方式以及code
实际上,在使用以上的一些方法的时候,每一个步骤都会生成一个RDD算子,如下图所示:
使用textFile按行读取文件的时候生成一个HadoopRDD算子,使用这个结果进行flatMap的时候再生成一个MapPartitionsRDD算子,然后基于这个结果再使用map转换数据,再生成一个MapPartitionsRDD算法,最后进行reduceByKey的时候生成一个ShuffledRDD算子,最后collect执行收集操作
可以看到实现WordCount这块也是进行了功能的叠加,与Java IO流非常相似,也属于一种装饰者设计模式
- RDD的数据处理方式类似于IO流,也有装饰者设计模式
- RDD的数据只有在调用
collect方法的时候,才会真正执行业务逻辑操作,是一种懒加载,之前的封装全部都是功能的扩展 - RDD本身不保存数据,但是IO可以临时保存一部分数据




