Spark(Python)学习(三)

RDD编程

RDD编程指的是Spark Core编程

RDD创建

(1)通过文件系统加载数据来创建RDD
Spark的SparkContext通过“.textFile()”读取数据,生成内存中的RDD。
在“.textFile()”括号中可以给出文件系统地址,支持的数据类型可以是:本地文件系统;分布式文件系统HDFS;加载云端文件(如Amazon S3等)。

下面是从本地文件系统中加载数据创建RDD的示例

>>> lines = sc.textFile("file:///<文件地址>/word.txt")
>>> lines.foreach(print)
Hadoop is good
Spark is fast
Spark is better

sc——SparkContext
在pyspark交互式执行环境中,系统默认创建好一个名称为sc的SparkContext对象。当编写独立应用程序时,需要使用代码来生成SparkContext对象。
“.foreach()”是一个高级函数,括号中可以传入一个函数作为参数。

下面是从分布式文件系统HDFS中加载数据

>>> lines = sc.textFile("hdfs://localhost:9000/user/hadoop/word.txt")
>>> lines = sc.textFile("/usr/hadoop/word.txt")
>>> lines = sc.textFile("word.txt")

这三条语句是完全等价的,可以使用其中任意一种方式。
localhost——主机名
9000——端口号
这两个都是在安装hadoop时人工配置好的。
/usr/hadoop——用户目录
//localhost:9000/usr/hadoop/——系统默认当前登录linux系统的用户在HDFS中所对应的用户主目录。这是全程路径,可以在加载的时候不使用全程路径。
直接使用文件名“word.txt”加载,表示该文件放在了当前用户主目录下。
这三条语句是完全等价的,可以使用其中任意一种方式。
(2)通过并行集合(数组)来创建RDD
并行指对集合进行并行化,这里通过调用SparkContext提供的Parallelize方法来实现并行化。
下面是通过并行集合(数组)创建RDD的实例

>>> array = [1,2,3,4,5]
>>> rdd = sc.parallelize(array)
>>> rdd.foreach(print)
1
2
3
4
5

在这里插入图片描述

RDD操作

(1)转换操作 Transformation
单个转换操作简单,但是多个转换操作组合后功能强大,可以玩成各种各样的业务逻辑。
在这里插入图片描述
每次转换操作都会产生不同RDD,来供一个操作使用 (RDD是只读的,只能在转换的过程中修改,再存放在新的RDD)。
由于惰性机制,这里的转换并不是真正发生计算,而是记录了转换的轨迹。
只有遇到了第一个动作类型操作,才会从头到尾进行计算。

RDD 常见转换操作:
在这里插入图片描述
filter——把RDD中元素进行一次过滤,把满足func要求的元素输出,不满足的过滤掉。func由用户设置。
map——做一对一映射,例如给每个学生成绩加5分,一对一的映射。
flatmap——虽然和map类似,但是完成的不是一对一映射,可能会输出0到多个结果。
groupByKey——根据Key值,按Key值相同的数据进行分组。
reduceByKey——在根据Key分组的基础上,使用func对分组值进行汇总计算。

  • filter(func): 筛选出满足函数func的元素,并返回一个新的数据集
>>> lines = sc.textFile("file:///usr/local/spark/mycode/rdd/word.txt")
>>> linesWithSpark = lines.filter(lambda line: "Spark" in line)
>>> linesWithSpark.foreach(print)
Spark is better
Spark is fast

在这里插入图片描述

  • map(func): 一对一映射,把每个元素依次传递到设定的函数执行
>>> data = [1,2,3,4,5]
>>> rdd1 =
sc.parallelize(data)
>>> rdd2 = 
rdd1.map(lambda x:x+10)
>>> rdd2.foreach(print)
11
12
13
14
15

在这里插入图片描述

>>> lines = 
sc.textFile("file:///usr/local/saprk/mycode/rdd/word.txt")
>>> words = lines.map(lambda line:line.split(" "))
>>> words.foreach(print)
['Hadoop', 'is', 'good']
['Spark', 'is', 'fast']
['Spark', 'is', 'better']

在这里插入图片描述

  • flatMap(func): 每个输入元素都可以映射到0或多个结果
>>> lines = 
sc.textFile("file:///usr/local/spark/mycode/rdd/word.txt")
>>> words = lines.flatMap(lambda line:line.split(" "))

在这里插入图片描述
执行flat实际上就是执行了两步操作,第一步执行“.map()”操作,拆分字符串构成列表;第二步把每个元素拍扁(flat),即在这里是将三个列表拍扁,得到单个单词,最终的flatMap结果。

  • groupByKey(): 实际上就是根据key进行分组,将key值相同的放在一组。
    作用的方式就是把groupByKey用到Key-Value为键值对的数据集,返回(K,Iterable)形式的数据集,Iterable为可迭代的数据集类型。即将Key相同的数据封装到一个Iterable对象中。
>>> words = sc.parallelize([("Hadoop",1),("is",1),("good",1),\
...("Spark",1),("is",1),("fast",1),("Spark",1),("is",1),("better",1)])
>>> words1 = words.groupByKey()
>>> words1.foreach(print)

在这里插入图片描述

  • reduceByKey(func): 在groupByKey的基础上对生成的列表中的值用func进行计算。
>>> words = sc.parallelize([("Hadoop",1),("is",1),("good",1),\
...("Spark",1),("is",1),("fast",1),("Spark",1),("is",1),("better",1)])
>>> words1 = words.reduceByKey(lambda a,b:a+b)
>>> words1.foreach(print)
('good',1)
('Hadoop',1)
('better',1)
('Spark',2)
('fast',1)
('is',3)

“.reduceByKey”首先做groupByKey(),把得到的(value,List)使用func函数求解。
下图为func函数用途,针对一组数据<“is”,<1,1,1>>,即现将第一个1传给容器1,第二个1传给容器2,容器1和容器2内数据进行f(.)计算,第三个1传给容器3,将第一次f(.)计算结果和容器3内数据进行f(.)计算,得到最终结果
在这里插入图片描述
(2)行动操作 Action
行动操作是真正触发计算的地方。
在这里插入图片描述
“.collect()”返回的结果是封装在列表里的。

>>> rdd = sc.parallelize([1,2,3,4,5])
>>> rdd.count()
5
>>> rdd.first()
1
>>> rdd.take(3)
[1,2,3]
>>> rdd.reduce(lambda a,b:a+b)
15
>>> rdd.collect()
[1,2,3,4,5]
>>> rdd.foreach(lambda elem:print(elem))
1
2
3
4
5

下图为“.reduce(lambda a,b:a+b)”操作的过程
在这里插入图片描述
(3)惰性机制
转换类操作并不计算,当遇到行动类操作才会触发从头到尾计算。

>>> lines =
sc.textFile("file:///user/local/spark/mycode/rdd/word.txt")
>>> lineLengths = lines.map(lambda s:len(s))
>>> totalLength =
lineLengths.reduce(lambda a,b:a+b)
>>> print(totalLength)

第一条指令“sc.textFile”是一个转换操作,并不会真正执行,只是记录轨迹,不会从底层加载数据。
第二条指令是将RDD的么一行拿来求该行的长度,这同样是一个转换操作(map是转换操作)。
第三条指令出现reduce,典型的行动类性操作,完成从头到尾计算。

持久化

当进行迭代计算时,经常需要多次重复使用同一组数据,如果不进行持久化,每次访问这组值都会重新生成一遍,代价很大。
持久化可以把多次访问的数据保存到内存中,下次使用时不用重复计算。
通过持久化(缓存)机制避免这种重复计算,使用persist()方法对一个RDD标记为持久化。“标记为持久化”指出现persist()语句的地方并不会马上计算生成RDD并将其持久化,而是要等遇到第一个行动操作触发真正计算后,才会把计算结果进行持久化。持久化的RDD将会被保留在计算节点的内存中被后面的行动操作重复使用。
下面为过程实例

>>> list = ['Hadoop","Spark","Hive"]
>>> rdd = sc.parallelize(list)
>>> print(rdd.count())	// 行动操作,触发一次真正从头到尾的计算
3
>>> print(','.join(rdd.collect()))	/ 行动操作,触发一次真正从头到尾的计算
Hadoop,Spark,Hive

‘,’.join(rdd.collect())——将列表内单词使用”,“作为间隔连接。

如何持久化
Spark提供了 .persist()方法 对一个RDD标记为持久化,并不会马上计算生成RDD并把它持久化。整个持久化真正执行的时机是触发第一次 动作类型操作 的时候,这时才是真正持久化。
.persist() 方法的不同参数
使用不同参数来表示不同级别的持久化。
(1).persist(MEMORY_ONLY)方法
表示把RDD作为反序列化的对象存在JVM中,如果内存不足则按“最近最少使用原则(LRU)”替换内容。

hadoop 支持三种调度器
先进先出的调度器: 最早的 hadoop 采用的是 FIFO(默认-先进先出的)调度器调度用户提交的作业。作业按照提交的顺序被调度,作业必须等待轮询到自己才能运行。 但是考虑到公平在多用户之间分配资源,设置了作业的优先级功能,但是不支持抢占式的。
公平调度器: 公平调度器的目标是让每一个用户公平的共享集群能力,充分的利用闲置的任务槽,采用“让用户公平的共享集群”的方式分配资源。作业放在作业池之中,每个用户拥有自己的作业池。提交的作业越多并不会因此获得更多的资源,公平调度器支持抢占式的机制,一个作业池中若没有公平的共享资源,则会将多余的资源空出来。
容量调度器: 集群中很多的队列组成的,这些队列具有一定的层次结构,每个队列都有一定的容量。每个队列的内部支持 FIIFO 方式。本质上容量调度器允许用户或则组织模拟出一个使用 FIFO 调度策略的独立 MApReduce 集群。

(2).persist(MEMORY_AND_DISK)方法
优先保存内存,如果内存不足,则将内存存放不下的部分保存到磁盘。
.cache()方法
为了方便使用,出现了.cache()方法,.cache()方法会调用 .perisit(MEMORY_ONLY)
在这里插入图片描述
一个RDD长期保存在内存空间对内存产生消耗,当预计该RDD后期不会重复使用后,需要手动释放。
.unpersis()方法
.unpersis()方法用于手动地把持久化的RDD从缓存中移除。

>>> list = ["Hadoop","Spark","Hive"]
>>> rdd = sc.parallelize(list)
>>> rdd.cache()	# 会调用persist(MEMORY_ONLY),但是,语句执行到这里,并不会缓存rdd,因为这时rdd还没有被计算生成
>>> print(rdd.count())	# 第一次行动操作,触发一次真正从头到尾的计算,这时上面的rdd.cache()才会被执行,把这个rdd放到缓存中
3
>>> print(','.join(rdd.collect()))	# 第二次行动操作,不需要触发从头到尾的计算,只需要重复使用上面缓存中的rdd
Hadoop,Spark,Hive

分区

分区主要有两大作用,增加并行度和减少通信开销。
(1)增加并行度:计算时可以同时在多个节点上发生计算。
在这里插入图片描述
(2)减少通信开销:
利用实例进行解释,在此实例中有两个表。userData表是一个非常庞大的表,有成百上千万的用户,每个用户包括UserID和UserInfo。
在这里插入图片描述
另一个表是Events表,这个表是一个小表,其包含两个字段,UserId和LinkInfo。用于记录用户在过去的5分钟内所访问的网站的链接信息。
当需要获取用户的名字和信息以及他所访问的网站,就需要将UserData和Events相连接。
在这里插入图片描述
这两个表的连接关系到分区问题。
在下图是没有进行分区的连接,这时连接代价高,产生昂贵的通信开销。
在这里插入图片描述
下图为分区后对UserData和Events两个表进行连接操作,例如让u1上只保存0~100万的ID的信息,u2上只保存100万~200万的ID的信息,以此类推进行事先的分区。
这时再做连接操作就变得非常简洁,只需要events表的数据分发,节省了大量的数据传输开销。
在这里插入图片描述
RDD分区原则
RDD分区原则是使得分区的个数尽量集群中CPU核心的数目。
在这里插入图片描述
因为一个分区会启动一个线程
在这里插入图片描述
并且针对Spark部署的多种模式(local、standalone、YARN、mesos),通过设置具体参数值来配置默认的分区数目。
参数“spark.default.parallelism”
(1)本地模式默认为本地机器的CPU数目。若设置了local[N],则默认为N。
(2)Apache Mesos模式,默认分区数目为8。
(3)Standalone或YARN模式,默认取集群中所有CPU核心数目总和同“2”之间取较大值,作为默认分区数目。
设置分区个数
手动设置分区数目,在调用textFile()和parallelize()方法时进行设置。
在这里插入图片描述
下面为创建RDD时手动指定分区个数实例

>>> list = [1,2,3,4,5]
>>> rdd = sc.parallelize(list,2)	// 设置两个分区

还可以使用repartition方法重新设置分区个数。通过转换操作得到新的RDD时,直接调用repartition方法。

>>> data = sc.parallelize([1,2,3,4,5],2)
>>> len(data.glom().collect())	# 显示data这个RDD的分区数量
2
>>> rdd = data.repartition(1)	# 对data这个RDD进行重新分区
>>> len(rdd.glom().collect())	# 显示rdd这个RDD的分区数量
1

为什么称之为弹性分式数据集,就是可以在计算过程中动态调整分区个数,这在计算中很有必要。

分区机制
(1)HashPartitioner(哈希分区)
(2)RangePartitioner(区域分区)
(3)自定义分区
在实际的编程中默认的哈希分区和区域分区两种分区方式,一般就能够满足实际的应用开发需求,但是也有需要自定义分区方式的情况。
下面用实例演示自定义分区方式。
在这里插入图片描述
下面为自定义分区函数,按传入参数key的尾数确定放入哪个分区,该文件保存为TestPartitioner.py

from pyspark import SparkConf, SparkContext

def MyPartitioner(key):
	print("MyPartitioner is running")
	print('The Key is %d' % key)
	return key%10

def main():
	print("The main function is running")
	conf = SparkConf().setMaster("local").setAppName("MyApp")
	sc = SparkContext(conf=conf)
	data = sc.parallelize(range(10),5)
	data.map(lambda x:(x,1))\
		.partitionBy(10,MyPartitioner)\
		.map(lambda x:x[0])\
		.saveAsTextFile("file:///usr/local/spark/mycode/rdd/partitioner")

if __name__=='__main__':
	main()

print(“MyPartitioner is running”) —— 表示函数正在运行
print(‘The Key is %d’ % key) —— 显示当前key值
return key%10 —— 返回key的尾数
SparkConf().setMaster(“local”).setAppName(“MyApp”) —— 这是标准写法,首先配置Master值为“local”模式。设定应用的名称为“MyApp”,设定好后可以在网页端看到这个名字。
SparkContext(conf=conf) —— 把上面定义好的上下文环境参数传输进来,生成一个SparkContext对象,这个对象就这里指挥官。
sc.parallelize(range(10),5) —— 生成0~9的整数,并对这几个数字分5个分区。
data.map(lambda x:(x,1)) —— 对当前RDD中的0~9,十个元素进行映射,得到10个键值对。
在这里插入图片描述
.partitionBy(10,MyPartitioner) —— 完成重分区,10为重分区个数,MyPartitioner为自定义的分区类。根据前面生成的键值对的键(Key)进行分区。 前面把0~9都变成(0,1)~(9,1)的键值对形式,是由于PartitionBy只能接收键值对类型的数据。
.map(lambda x:x[0]) —— 前面的操作得到了重分区后的键值对,但是保存所需要的数据类型是0,1,2,…,9,所以需要再次映射操作。x[0]是键值对的第一个元素。
在这里插入图片描述
.saveAsTextFile() —— 写入文件,括号中是必须是目录地址,因为如果分了10个分区,每个分区会单独生成一个文件。
下面是运行TestPartitioner.py的两种方式

$ cd <TestPartitioner.py文件目录>
$ python3 TestPartitioner.py

$ cd <TestPartitioner.py文件目录>
$ /usr/local/spark/bin/spark-submit TestPartitioner.py

“ /usr/local/spark”为Spark安装目录
在这里插入图片描述

综合实例(如何进行词频统计)

有一个word.txt,包含多个英文文本行。对它进行词频统计。

>>> lines =sc. \
... textFile("file:///usr/local/spark/mycode/rdd/word.txt")
>>> wordCount = lines.flatMap(lambda line:line.split("")).\
... map(lambda word:(word,1)).reduceByKey(lambda a,b:a+b)
>>> print(wordCount.collect())
[('good',1),('Spark',2),('is',3),('better',1),('Hadoop',1),('fast',1)]

在这里插入图片描述
在这里插入图片描述
这里演示的单机上执行的例子,实际情况一般是在多机上运行。可以把Hadoop和Spark同时部署在同个集群中,即把集群中的某个节点既作为HDFS的存储节点,同时也作为Spark的WorkerNode。
Spark的计算组件和HDFS的存储组件放在了同一台机器上。那么就可以让Spark对保存在HDFS中的实例文件进行并行的词频统计,再将结果进行汇总。

在这里插入图片描述
下面为分布式词频统计计算过程
在这里插入图片描述

键值对RDD的创建

称之为键值对RDD的原因是RDD中的每一个元素都是一个键值对 (key, value)。
下面演示生成键值对RDD的两种方式
(1)加载文件后,以空格为分隔符,使用map()函数创建键值对RDD

>>> lines = 
sc.textFile("file:///usr/local/spark/mycode/pairrdd/word.txt")
>>> pairRDD = lines.flatMap(lambda line:line.split("")).map(lambda word:(word,1))
>>> pairRDD.foreach(print)
('I',1)
('love',1)
('Hadoop',1)

(2)通过并行集合(列表)创建RDD

>>> list = ["Hadoop","Spark","Hive","Spark"]
>>> rdd = sc.parallelize(list)
>>> pairRDD = rdd.map(lambda word:(word,1))
>>> pairRDD.foreach(print)
(Hadoop,1)
(Spark,1)
(Hive,1)
(Spark,1)

常用的键值对RDD转换操作

—— reduceByKey和groupByKey

(1)reduceByKey(func)
功能:使用func函数合并具有相同键的值。

>>> pairRDD = 
sc.parallelize([("Hadoop",1),("Spark",1),("Hive",1),("Spark",1)])
>>> pairRDD.reduceByKey(lambda a,b:a+b).foreach(print)
('Spark',2)
('Hive',1)
('Hadoop',1)

(2)groupByKey()
功能:对具有相同键的值进行分组,即不进行聚合计算,而是列表计算。
在这里插入图片描述
将相同值的元素归并成一个列表,并不会对值的列表进行聚合计算。

>>> list = 
[("spark",1),("spark",2),("hadoop",3),("hadoop",5)]
>>> pairRDD = sc.parallelize(list)
>>> pairRDD.groupByKey()
PythonRDD[27] at RDD at PythonRDD.scala:48
>>> pairRDD.groupByKey().foreach(print)

groupByKey和reduceByKey的区别

在这里插入图片描述
下面用实例演示两种键值对转换操作

>>> words = ["one","two","two","three","three","three"]
>>> wordPairsRDD = sc.parallelize(words).map(lambda word:(word,1))
>>> wordCountsWithReduce = wordPairsRDD.reduceByKey(lambda a,b:a+b)
>>> wordCountsWithReduce.foreach(print)
('one',1)
('two',2)
('three',3)
>>> wordCountsWithGroup = wordPairsRDD.groupByKey().\
... map(lambda t:(t[0],sum(t[1])))
>>> wordCountsWithGroup.foreach(print)
('two',2)
('three',3)
('one',1)

在本实例中t的一个元素(one,1)的t[0]为‘one’,t[1]为‘1’;另一个元素(two,(1,1))的t[0]为‘two’,t[1]为‘(1,1)’。
在这里插入图片描述

—— keys, values, sortByKey, mapValues, join

(1)keys
功能:把键值对RDD的key返回形成一个新的RDD。

>>> list = 
[("Hadoop",1),("Spark",1),("Hive",1),("Spark",1)]
>>> pairRDD = sc.parallelize(list)
>>> pairRDD.keys().foreach(print)
Hadoop
Spark
Hive
Spark

(2)values
功能:把键值对RDD中的value返回形成一个新的RDD。

>>> list = 
[("Hadoop",1),("Spark",1),("Hive",1),("Spark",1)]
>>> pairRDD = sc.parallelize(list)
>>> pairRDD.values().foreach(print)
1
1
1
1

(3)sortByKey()
功能:返回一个根据键排序的RDD。

>>> list = 
[("Hadoop",1),("Spark",1),("Hive",1),("Spark",1)]
>>> pairRDD = sc.parallelize(list)
>>> pairRDD.foreach(print)
('Hadoop',1)
('Spark',1)
('Hive',1)
('Spark',1)
>>> pairRDD.sortByKey().foreach(print)
('Hadoop',1)
('Hive',1)
('Spark',1)
('Spark',1)

sortByKey()括号内可以填“True”或“False”,默认括号内为True,按升序排序,否则降序排序。

sortByKey()和sortBy()的区别

>>> d1 = sc.parallelize([("c",8),("b",25),("c",17),("a",42)\
... ("b",4),("d",9),("e",17),("c",2),("f",29),("g",21),("b",9)])
>>> d1.reduceByKey(lambda a,b:a+b).sortByKey(False).collect()
[('g',21),('f',29),('e',17),('d',9),('c',27),('b',38),('a',42)]

sortByKey()是按key值排序,当需要按value排序时就用到了sortBy()。

>>> d1 = sc.parallelize([("c",8),("b",25),("c",17),("a",42)\
... ("b",4),("d",9),("e",17),("c",2),("f",29),("g",21),("b",9)])
>>> d1.reduceByKey(lambda a,b:a+b).sortBy(lambda x:x,False).collect()
[('g',21),('f',29),('e',17),('d',9),('c',27),('b',38),('a',42)]
>>> d1.reduceByKey(lambda a,b:a+b).sortBy(lambda x:x[0],False).collect()
[('g',21),('f',29),('e',17),('d',9),('c',27),('b',38),('a',42)]
>>> d1.reduceByKey(lambda a,b:a+b).sortBy(lambda x:x[1],False).collect()
[('a',42),('b',38),('f',29),('c',27),('g',21),,('e',17),('d',9)]

(4)mapValues(func)
功能:对键值对RDD中的每个value都应用一个函数,key不会发生改变。

>>> list = 
[("Hadoop",1),("Spark",1),("Hive",1),("Spark",1)]
>>> pairRDD = sc.parallelize(list)
>>> pairRDD1 = pairRDD.mapValues(lambda x:x+1)
>>> pairRDD1.foreach(print)
('Hadoop',2)
('Spark',2)
('Hive',2)
('Spark',2)

(5)join
join表示内连接。内连接是对于给定的两个输入数据集(K,V1)和(K,V2),只有在两个数据集中都存在的key才会被输出,最终得到一个(K,(V1,V2))类型的数据集。

>>> pairRDD1 = sc.\
... parallelize([("spark",1),("spark",2),("hadoop",13),("hadoop",5)])
>>> pairRDD2 = sc.parallelize([("spark","fast")])
>>> pairRDD3 = pairRDD1.join(pairRDD2)
>>> pairRDD3.foreach(print)
('spark',(1,'fast'))
('spark',(2,'fast'))

两个RDD中只有key值为“spark”的元素有同样的key值,所以将具有相同key值的元素的value值归并。

综合实例(计算每种图书每天平均销量)

key值对应图书名称,value值对应某天图书销量。

>>> rdd = sc.parallelize([("spark",2),("hadoop",6),("hadoop",4),("spark",6)])
>>> rdd.mapValues(lambda x:(x,1)).\
... reduceByKey(lambda x,y:(x[0]+y[0],x[1]+y[1])).\
... mapValues(lambda x:x[0]/x[1]).collect()
[('hadoop',5.0),('spark',4.0)]

rdd.mapValues(lambda x:(x,1)) —— key不变,value变为键值对形式。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

文件数据读写

文件数据读写包括本地文件系统的数据读写分布式文件系统HDFS的数据读写
(1)本地文件系统的数据读写
从文件中读取数据创建RDD

>>> textFile = sc.\
... textFile("file:///usr/local/spark/mycode/rdd/word.txt")
>>> textFile.first()
'Hadoop is good'

textFile.first() —— 读出第一行。
由于Spark采用惰性执行机制,所以即使输入了错误的语句,spark-shell也不会马上报错。
所以“.textFile”加载后,后面若没有遇到行动类型操作,并不会真正发生加载。
把RDD写入到文本文件中

>>> textFile = sc.\
... textFile("file:///usr/local/spark/mycode/rdd/word.txt")
>>> textFile.\
... saveAsTextFile("file:///usr/local/spark/mycode/rdd/writeback") 

“saveAsTextFile()”的括号内是一个目录。
再次把数据加载在RDD中

>>> textFile = sc.\
... textFile("file:///usr/local/spark/mycode/rdd/writeback")

再次加载只需要把刚才保存的目录名称放入sc.textFile()内,就会把目录中的所有文件内容加载进来。

(2)分布式文件系统HDFS的数据读写

>>> textFile = sc.textFile("hdfs://localhost:9000/user/hadoop/word.txt")
>>> textFile.first()

全称路径方式和另外两种路径方式等价

scala> val textFile = 
sc.textFile("hdfs://localhost:9000/user/hadoop/word.txt")
scala> val textFile = sc.textFile("/user/hadoop/word.txt")
scala> val textFile = sc.textFile("word.txt")

把RDD中的数据保存到HDFS文件中

>>> textFile = sc.textFile("word.txt")
>>> textFile.saveAsTextFile("writeback")
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值