<Spark><Programming><RDDs>
Introduction to Core Spark Concepts
- driver program:
- 在集群上启动一系列的并行操作
- 包含应用的main函数,定义集群上的分布式数据集,操作数据集
- 通过SparkContext对象访问spark,这表示了与计算集群的连接
- executors:
- the place to run the operations
- Spark automatically takes ur function and ships it to executor nodes.
Programming with RDDs
- RDD: spark's core abstraction for working with data.
- RDD简单来说就是元素的分布式集合
- 在Spark中所有的工作都可以表示成创建一个新的RDDs,转换已有的RDDs,或者是在RDDs上运行operations
RDD Basics
- An immutable distributed collection of objects.
- 每个RDD被split成多个partitions,每个partition可能在cluster的不同节点上被计算
- RDD的创建:
- loading一个外部数据集
- distributing对象集合(eg: a list or set)
- transformations:从原RDD创建一个新的RDD
- actions:基于RDD计算一个result,这个结果要么返回给driver program,要么存储到外部存储系统(eg: HDFS)
- RDD.persist():由于缺省情况下,每次运行action的时候RDDs是重新计算的。如果对RDD进行persist,那么该RDD会persist到内存(或disk),下次action的时候可以reuse。
RDD操作:(区分这两种操作的原因是Spark的计算是lazy fashion的
Creating RDDs
- parallelize()
val lines = sc.parallelize(List("pandas", "I like pandas"))
- textFile()
val lines = sc.textFile("/path/to/README.md")
RDD Operations
- Transformation & Action
Transformations
- Compute lazily
- 没有改变原RDD(immutable),而是生成了新的RDD,spark会保存这一系列依赖关系(lineage)
Actions
- Actually do something with our dataset
Passing Functions to Spark
- Scala: we can pass in functions defined inline, references to methods, or static functions
- Scala: 我们所传送的函数和其中的数据引用需要被序列化(实现Java的Serializable接口)
- 如果我们pass一个对象中的函数,或者包含了对象中的字段的引用(eg: self.field),spark会把整个对象发送给worker nodes,这会远大于你所需要的信息。并且如果你的对象不能持久化(pickle in python)的话,会导致是你的程序失败。举一个python的例子:
错误示范如下:
正确示范:(提取对象中你所需的字段为局部变量,然后传进去)
- 同样的,对scala我们也要尽量避免上述情况,而且要注意的是在scala中不需要显示的self.或者this.,所以这种情况显得很不明显,但仍然要注意。举个栗子
如果在scala中出现了NotSerializableException,那么多半是因为引用了一个不可序列化的类中的变量或字段。所以,传送一个局部的可序列化的变量或函数才是安全的。
- Any code that is shared by RDD transformations must always be serializable.
Common Transformations and Actions
Basic RDDs
- 我们首先介绍基本的RDD操作,它们可以执行在所有RDDs上而不用管数据
Element-wise transformations
- map() and filter()
- flatMap(): 为每一个输入元素产生多个输出元素。返回的是一个迭代器iterator
val lines = sc.parallelize(List("hello world", "hi"))
val words = lines.flatMap(line => line.split(" "))
Psedudo set operations
- 一些简单的集合操作:(需要RDDs是同一类型的)
- RDD1.distinct() --> 十分昂贵的操作,需要shuffle all data over the network
- RDD1.union(RDD2) --> 最简单的集合操作,会保留原RDD中的重复值
- RDD1.intersection(RDD2) --> 需要去重(来识别共同元素),因而也需要shuffle
- RDD1.substract(RDD2) --> perform shuffle
- RDD1.cartesian(RDD2) --> returns all possible pairs of (a, b) where a is in the source RDD and b is in the other RDD .十分昂贵
- 为什么叫psedudo即假的集合操作呢,因为这里的集合丢失了一个重要特性:uniqueness即元素的唯一性。因为我们经常有duplicates
Actions
- reduce() & fold() :都需要返回值和RDD中的元素保持同一类型。
fold()接收与reduce接收的函数签名相同的函数,另外再加上一个初始值作为第一次调用的结果.
val sum = rdd.reduce((x, y) => x + y)
- aggregate(): frees us from the constraint of having the return be the same types as the RDD we are working on.
aggregate的函数原型:
def aggregate [U: ClassTag] (zeroValue: U) (seqOp: (U,T)=>U,combOp: (U,U)=>U):U
可以看到,(zeroValue: U)是给定的一个初值,后半部分有两个函数,seqOp相当于是在各个分区里进行的聚合操作,它支持(U, T) => U,也就是支持不同类型的聚合。comOp是将sepOp后的结果聚合,此时的结果全部是U类,也就是只能进行同构聚合。
一个经典的例子是求平均值。即先用seqOp求出各个分区中的sum和个数,再将seqOp后的结果聚合得到总的sum和总的个数。
- collect(): 返回整个RDD中的内容,常用于单元测试,因为它需要你的整个数据集能够fit on a single machine.
- take(n): 返回RDD中的n个元素,并且试图最小化所访问的partition数,所以它可能会返回一个biased collection。
- takeSample(withReplacement, num, seed): allows us to take a sample of our data either with or without replacement.
- foreach(): 可以允许我们在每个元素上执行操作or计算,而不需要把元素送回driver
Converting Between RDD Types
- 一些functions只在某些特定类型RDD上可用。比如mean(), variance()只用于numericRDDs, join()只用于key/value pair RDDs.
- 在scala和Java中,这些方法未在标准RDD类中定义,因此为了访问这些附加的功能,我们需要确保我们得到了正确的specialized class。
Scala
- 在scala中。RDDs的转换可以通过使用隐式转换(using implicit conversions)来自动进行。
- 看一段RDD.scala源码中的介绍
- 关于scala隐式转换: 当对象调用类中不存在的方法或成员时,编译器会自动将对象进行隐式转换
- 隐式转换带来的confusion:当你在RDD上调用mean()这样的方法时,你会发现在RDDclass 的Scaladocs中找不到mean()方法,但是该方法能成功调用是由于实现了RDD[Double]到DoubleRDDFunctions的隐式转换。
Persistence(Caching)
- As discussed earlier, Spark RDDs是惰性求值的,如果我们想要多次使用同一个RDD的话,Spark通常会每次都重新计算该RDD和它所有的依赖。这对于迭代算法是十分昂贵的。
- 一个比较直观的例子如下,每次action的时候都会重新计算:
- 为了避免多次重复计算同一个RDD,我们可以让Spark来persist数据。这样的话,计算该RDD的那个节点会保存它们的partition。
- 如果有数据持久化的节点fail掉了,Spark会在需要的时候重新计算丢失的partitons。当然我们也可以通过在多个节点保存副本的方式来避免节点故障时的slowdown。
- Spark有很多levels of persistence供选择。
Level Space Used CPU time In Memory On Disk Comments MEMORY_ONLY
High Low Y N MEMORY_ONLY_SER
Low High Y N MEMORY_AND_DISK
High Medium Some Some Spils to disk if there is too much data to fit in memory. MEMORY_AND_DISK_SER
Low High Some Some Spills to disk if there is too much data to fit in memory. Stores serialized representation in memory.
DISK_ONLY
Low High N Y - 在Java和scala中,缺省的情况下persist()回将未序列化的对象数据保存在JVM的堆中。
- 如果你试图在内存中cache过多的数据,Spark将会自动驱逐旧的partitions,使用最少最近使用(Least Recently Used, LRU)缓存策略。对于MEMORY_ONLY level,下次访问的时候会重新计算这些被驱逐的分片。
- 由于Spark'的各种机制,无论使用哪种level,你都可以不用担心job breaking。但是缓存不必要的数据将会导致有用数据被驱逐,从而增加重计算的时间。
- Spark提供了unpersist()方法可以让你手工地将RDD移除缓存。
Off-heap caching is experimental and uses Tachyon. If you are interested in off-heap caching with Spark, take a look at the Running Spark on Tachyon guide.
<Spark><Programming><RDDs>的更多相关文章
- 简单物联网:外网访问内网路由器下树莓派Flask服务器
最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...
- 利用ssh反向代理以及autossh实现从外网连接内网服务器
前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...
- 外网访问内网Docker容器
外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...
- 外网访问内网SpringBoot
外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...
- 外网访问内网Elasticsearch WEB
外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...
- 怎样从外网访问内网Rails
外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...
- 怎样从外网访问内网Memcached数据库
外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...
- 怎样从外网访问内网CouchDB数据库
外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...
- 怎样从外网访问内网DB2数据库
外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...
- 怎样从外网访问内网OpenLDAP数据库
外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...
随机推荐
- cmd net use
前提条件 启动服务 首先保证目标的IPC服务启动,服务为lanmanWorkstation,显示名为Workstations 端口 telnet目标计算机lanmanWorkstation服务的两个端 ...
- 电脑用U盘启动
除了根据提示按DEL或者F2进入到BIOS界面更改设置之外. 还可以在开机时按F8或F12进入到引导界面,可直接选择USB. 当把登录用户登录,其他用户都被禁用时,电脑登不进去.要制作启动U盘,进入到 ...
- CentOS7 安装Nginx 1.14:
nginx-1.14.2.tar.gz:下载:wget http://nginx.org/download/nginx-1.14.2.tar.gz 安装nginx: yum install ...
- ubuntu Sublime Text 2编辑器安装
官网下载http://www.sublimetext.com/2 选择合适的包下载回来的格式是.tar.bz2格式,需要进行解压. 1,解压:tar -xvf Sublime\ Text\ 2.0.2 ...
- upsource初探
在JetBrains 的官网上,看到codereview的工具 upsource ,https://www.jetbrains.com/upsource/ 官方的英文文档 来看下博客园上有博主简单的 ...
- mybatis的update使用选择
更新后台设置时,会分多个页面更新同一个表中的数据,愿想是尽量减少sql请求数据量并且减少重复代码. 比如博客园的: 假如只有一个用户信息表,这样的话每个页面只更新部分字段. 这种情况下的更新推荐在xm ...
- [LightOJ 1027] A Dangerous Maze
A Dangerous Maze You are in a maze; seeing n doors in front of you in beginning. You can choose any ...
- 【转】Entity Framework教程(第二版)
源起 很多年前刚毕业那阵写过一篇关于Entity Framework的文章,没发首页却得到100+的推荐.可能是当时Entity Framework刚刚发布介绍EF的文章比较少.一晃这么多年过去了,E ...
- Linux网卡性能查看(CentOS)
一.ethtool查看网卡带宽 ethtool eth0 #eth0为网卡名,使用ifconfig查看当前使用的网卡 Speed表示网卡带宽,Duplex表示工作模式,Supported link m ...
- Tomcat修改版本号教程(CentOS)
1 到apache-tomcat安装目录下的lib子文件夹,找到catalina.jar备份该文件然后将该文件下载到本地. 2 使用winrar等工具直接打开该jar包进入到org/apache/ca ...