Spark存儲與讀取文件方法小結

http://blog.csdn.net/buring_/article/details/42424477   mark

一:Spark中常常面臨這RDD的存儲問題,記錄一下常常面臨的幾種情況。saveAsObjectFile, SequenceFile, mapFile, textFile我就不說了。

首先:在寫文件的時候,經常輸出的目錄以及存在,需要一個刪掉目錄以及存在的情況。大致功能如下

[java] view plain copy
  1. def checkDirExist(sc:SparkContext,outpath:String) = {  
  2.   logInfo("check output dir is exists")  
  3.   val hdfs = FileSystem.get(new URI("hdfs://hdfs_host:port"),sc.hadoopConfiguration)  
  4.   try{  
  5.     hdfs.delete(new Path(outpath),true//這裏已經new 目錄了,刪除再說,總之是刪了  
  6.     logInfo("輸出目錄存在,刪除掉:%s".format(outpath))  
  7.   } catch {  
  8.     case _:Throwable => logWarning("輸出目錄不存在,不用刪除"//永遠不會來吧  
  9.   }  
  10. }  

1)存取對象,saveAsObjectFile ,十分方便,類似於python的cPickle.主要用法如下:
比如有一個

[java] view plain copy
  1. val rdd:RDD[(Long,Array[Double])]  
  2. rdd.saveAsObjectFile(outpath)  
  3.   
  4. 讀取對象文件,需要指定類型  
  5. val input:RDD[(Long,Array[Double])] = sc.objectFile[(Long,Array[Double])](outpath)  

2)有時候需要節約空間,這樣就需要存儲序列化文件。如

[java] view plain copy
  1. val rdd: RDD[(Long, Array[Byte])]  
  2. new SequenceFileRDDFunctions(rdd).saveAsSequenceFile(outpath)  
  3. 這裏需要注意序列化時候,Long,Array都需要一個隱式轉換函數,如下:  
  4. implicit def arrayBytetoBytesArray(bytes:Array[Byte]):BytesWritable = new BytesWritable(bytes)  
  5. implicit  def long2LongWritable(ll:Long):LongWritable = new LongWritable(ll)  
  6.   
  7. 讀取序列化文件:  
  8. val rdd = sc.sequenceFile(dir+"/svd",classOf[LongWritable],classOf[BytesWritable]).map{case(uid,sessions)=>  
  9.   sessions.setCapacity(sessions.getLength)  
  10.   (uid.get(),sessions.getBytes.clone())  
  11. }  
這裏需要注意的是,讀取序列化文件,默認複用了同樣的Writable object for each record, 也就導致了返回的RDD將會創建許多引用到同一個對象,我被這個坑了好久。因此這裏需要將Array[Byte] 拷貝出來,不然所以的數據都是一樣的,Long不是引用對象不需要。

3)有時候需要存儲mapFile,用來根據key 快速索引。實踐發現,索引的確很快,而且節約存儲空間。
存儲mapFile文件,需要注意是現要排序以後才能輸出,爲了快速索引,排序也是可以理解的嘛。

[java] view plain copy
  1. val temp: RDD[(Long, Array[Byte])]  
  2. val mapfile = temp.toArray().sortBy(e => e._1)  
  3. var writer: MapFile.Writer = null  
  4. val conf = sc.hadoopConfiguration  
  5. val fs = FileSystem.get(URI.create(dir+"/merge"),conf)  
  6. val key = new LongWritable()  
  7. val value = new BytesWritable()  
  8. try{  
  9.   writer = new Writer(conf,fs,dir+"/merge",classOf[LongWritable],classOf[BytesWritable])  
  10.   //這裏不知道設置多少比較合適,感覺都ok  
  11.   writer.setIndexInterval(1024)  
  12.   for(ele <-mapfile){  
  13.     key.set(ele._1)  
  14.     value.set(ele._2)  
  15.     writer.append(key,value)  
  16.   }  
  17. }finally {  
  18.   IOUtils.closeStream(writer)  
  19. }  
  20.   
  21. 快捷根據key 來檢索value  
  22. val reader = new Reader(FileSystem.get(sc.hadoopConfiguration),  
  23.   dir,sc.hadoopConfiguration)  
  24.   
  25. val key = new LongWritable(args(1).toLong)  
  26. val value = new BytesWritable()  
  27.   
  28. reader.get(key,value)  
  29. value.setCapacity(value.getLength)  
  30. val bytes = value.getBytes  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章