Spark从零到一 (三)Spark之广播、共享、缓存

                                Spark之广播、共享、缓存

一、概述

在spark程序中,当一个传递给Spark操作(例如map和reduce)的函数在远程节点上面运行时,Spark操作实际上操作的是这个函数所用变量的一个独立副本。这些变量会被复制到每台机器上,并且这些变量在远程机器上的所有更新都不会传递回驱动程序。通常跨任务的读写变量是低效的,但是,Spark还是为两种常见的使用模式提供了两种有限的共享变量:广播变(broadcast variable)和累加器(accumulator)

 

二、广播变量broadcast variable

2.1 为什么要将变量定义成广播变量?

如果我们要在分布式计算里面分发大对象,例如:字典,集合,黑白名单等,这个都会由Driver端进行分发,一般来讲,如果这个变量不是广播变量,那么每个task就会分发一份,这在task数目十分多的情况下Driver的带宽会成为系统的瓶颈,而且会大量消耗task服务器上的资源,如果将这个变量声明为广播变量,那么知识每个executor拥有一份,这个executor启动的task会共享这个变量,节省了通信的成本和服务器的资源。

2.2 广播变量图解

错误的,不使用广播变量

正确的,使用广播变量的情况

2.3 如何定义一个广播变量?

// 在java 中 创建广播变量
final int factor = 3;
final Broadcast<Integer> factoryBroatCast = sc.broadcast(factor);
		

2.4 如何还原一个广播变量?

2.5 定义广播变量需要的注意点?
List<Integer> listNumber= Arrays.asList(1,2,3,4,5);
		JavaRDD<Integer> rddList = sc.parallelize(listNumber);
		JavaRDD<Integer> result = rddList.map(new Function<Integer, Integer>() {
			public Integer call(Integer integer) throws Exception {
				// 在java 中 获取广播变量
				return integer * factoryBroatCast.value();
			}
		});

变量一旦被定义为一个广播变量,那么这个变量只能读,不能修改

2.6 注意事项

1、能不能将一个RDD使用广播变量广播出去?

       不能,因为RDD是不存储数据的。可以将RDD的结果广播出去。

2、 广播变量只能在Driver端定义,不能在Executor端定义。

3、 在Driver端可以修改广播变量的值,在Executor端无法修改广播变量的值。

4、如果executor端用到了Driver的变量,如果不使用广播变量在Executor有多少task就有多少Driver端的变量副本。

5、如果Executor端用到了Driver的变量,如果使用广播变量在每个Executor中只有一份Driver端的变量副本。

 

三、累加器 

3.1 为什么要将一个变量定义为一个累加器?

在spark应用程序中,我们经常会有这样的需求,如异常监控,调试,记录符合某特性的数据的数目,这种需求都需要用到计数器,如果一个变量不被声明为一个累加器,那么它将在被改变时不会再driver端进行全局汇总,即在分布式运行时每个task运行的只是原始变量的一个副本,并不能改变原始变量的值,但是当这个变量被声明为累加器后,该变量就会有分布式计数的功能。

3.2 图解累加器

错误的图解

正确的图解

3.3 如何定义一个累加器?

		 Accumulator<Integer> accumulator = sc.accumulator(0);

3.4 如何还原一个累加器?

accumulator.add(1);
accumulator.value();

3.5 注意事项

1、 累加器在Driver端定义赋初始值,累加器只能在Driver端读取最后的值,在Excutor端更新。

2、累加器不是一个调优的操作,因为如果不这样做,结果是错的

 

四:如何使用spark缓存

public static void noCache() {

		JavaRDD<String> list = sc.textFile("test.log");
		long beginTime = System.currentTimeMillis();
		long count = list.count();
		System.out.println("无持久化第一次" + (System.currentTimeMillis() - beginTime));

		beginTime = System.currentTimeMillis();
		count = list.count();
		System.out.println("无持久化第二次" + (System.currentTimeMillis() - beginTime));
	}

	public static void cache() {

		JavaRDD<String> list = sc.textFile("test.log").cache();
		long beginTime = System.currentTimeMillis();
		long count = list.count();
		System.out.println("持久化第一次" + (System.currentTimeMillis() - beginTime));

		beginTime = System.currentTimeMillis();
		count = list.count();
		System.out.println("持久化第二次" + (System.currentTimeMillis() - beginTime));

	}

运行程序会发现,没有缓存的代码两次执行的实际都差不多,有缓存的代码第二次是直接返回的并没有经过计算所以时间会大大降低。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值