Spark缓冲、容错机制

一.缓冲

	文件太大的时候,不会全部放到内存中,实际文件大小30M,放到内存中达到90M:因为写入的文件当中存放的是二进制,而读取到内存中以后,使用Java对象序列化方式
	这种序列化会占用更大的空间,所以比实际大小要大
	
	实际上不会将内存全部占用,要给程序运行留下足够的内存
	
	注意:
	cache可以提高程序运行速度,但是如果使用一次就没必要cache,常用于反复的使用
	cache既不是transformation也不是action,因为没有生成新的RDD, 也没有立即执行
	
	cache不建议直接将hdfs的数据直接cache
		   建议将hdfs的数据过滤后缓存
		   
	使用完毕后清空缓存:
	unpersist()

用法:
RDD.cache
二.容错机制
相关知识:checkpoint是建立检查点,类似于快照,例如在spark计算里面,计算流程DAG非常长,服务器需要将整个DAG计算完成得到结果,但是如果在这很长的计算流程中突然中间算出的
数据丢失了,spark又会根据RDD的依赖关系从头到尾计算一遍,这样很费性能,当然我们可以将中间计算的结果通过cache或者persist方法内存或者磁盘中,但是这样也不能保证数据完全不能丢失
存储的这个内存出问题或者磁盘坏了,也会导致spark从头再根据RDD计算一遍,所以就有了checkpoint,其中checkpoint的作用是将DAG中比较重要的中间数据做一个检查点将结果
放在一个高可用的地方(通常这个地方是HDFS里面)

	(*)checkpoint到底是什么和需要用checkpoint解决什么问题?
		1)spark在生产环境下经常面临transformation的RDD非常多,(例如一个Job中包含一万个RDD),或者是具体的transformation产生的RDD本身计算特别复杂和耗时(例如计算时长超过1个小时)
			可能业务比较复杂,此时我们必须要考虑对计算结果的持久化
		
		2)spark是擅长多步骤迭代计算,同时擅长基于Job的复用,这个时候如果曾经可以对计算结果的过程进行复用,就可以极大地提升效率,因为有时候有共同的步骤,可以避免重复计算
		3)如果采用cache将数据存放到内存的话,虽然最快但是也是最不可靠,即使放到磁盘也不可靠,都会坏掉
		4)checkpoint的产生就是为了相对而言更加可靠的持久化数据,在checkpoint可以指定数据存放到本地(HDFS)并且多个副本,这就天然的借助HDFS高可靠的特征
		5)checkpoint是针对整个RDD计算链条中特别需要数据持久化的环节(后面反复使用的RDD)
	(*)缺点:
		通过检查点checkpoint来实现,缺点:产生i/o
	(*)复习:HDFS的检查点:由SeconderyNameNode进行日志合并
			Oracle中,数据也是由检查点的,如果产生检查点,会以最高优先级唤醒数据库写进程,将内存中的脏数据写到数据文件中(持久化)
	
	(*)检查点可以将中间结果保存起来
		两种方式
		(*)本地目录(测试环境)
		(*)HDFS的目录(生产环境)
			注意:这种模式,需要将spark-shell运行在集群上

2.使用checkpoint
//先创建一个文件
scala> sc.setCheckpointDir(“hdfs://bigdata02:9000/checkpoint0927”)
//创建一个RDD
scala> val rdd1 = sc.parallelize(1 to 1000)
rdd1: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[8] at parallelize at :24
//启动容错机制
scala> rdd1.checkpoint
//触发容错
scala> rdd1.collect

执行的时候相当于走了两次流程,sum的时候前面计算一遍,然后checkpoint又会计算一遍,所以我们一般先进行cache然后做checkpoint就会只走一次流程了吧
checkpoint的时候就会从刚cache到内存中取数据写入到hdfs中

			 其中作者也说明了,在checkpoint的时候强烈建议先进行cache,并且当你checkpoint执行成功后,那么前面所有的RDD依赖都会被销毁
			 /**
			   * Mark this RDD for checkpointing. It will be saved to a file inside the checkpoint
			   * directory set with `SparkContext#setCheckpointDir` and all references to its parent
			   * RDDs will be removed. This function must be called before any job has been
			   * executed on this RDD. It is strongly recommended that this RDD is persisted in
			   * memory, otherwise saving it on a file will require recomputation.
			   */

猜你喜欢

转载自blog.csdn.net/qq_41166135/article/details/82873675