Introduction to Core Spark Concepts

  • driver program:
    1. 在集群上启动一系列的并行操作
    2. 包含应用的main函数,定义集群上的分布式数据集,操作数据集
    3. 通过SparkContext对象访问spark,这表示了与计算集群的连接
  • executors
    1. the place to run the operations
    2. 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的创建:
    1. loading一个外部数据集
    2. distributing对象集合(eg: a list or set)
  • RDD操作:(区分这两种操作的原因是Spark的计算是lazy fashion的

    1. transformations:从原RDD创建一个新的RDD
    2. actions:基于RDD计算一个result,这个结果要么返回给driver program,要么存储到外部存储系统(eg: HDFS)
  • RDD.persist():由于缺省情况下,每次运行action的时候RDDs是重新计算的。如果对RDD进行persist,那么该RDD会persist到内存(或disk),下次action的时候可以reuse。

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>的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. Linux 权限管理命令

    第四章(二)权限管理命令 Linux常用命令(二)权限管理命令

  2. python记录_day06

    一.小数据池 注意大前提!!!! 小数据池只针对整数.字符串和bool值,因为这些数据是不可变的,这样数据的共享才安全 小数据池也称为小整数缓存机制或驻留机制,是指在不同代码块创建部分小数据对象(具体 ...

  3. 优先队列优化dij算法

    之前已经弄过模板了,但那个复杂一点,这个就是裸的dij,用起来更方便 输入格式:n,m,s,d分别是点数,边数,起点,终点 之后m行,输入x,y,z分别是两点即权值 题目链接:https://www. ...

  4. 『MXNet』第一弹_基础架构及API

    MXNet是基础,Gluon是封装,两者犹如TensorFlow和Keras,不过得益于动态图机制,两者交互比TensorFlow和Keras要方便得多,其基础操作和pytorch极为相似,但是方便不 ...

  5. 第一阶段——站立会议总结DAY07

    未做,有一些作业比较赶,所以,先搁置了它.

  6. arguments.callee用法

    arguments.callee 在哪一个函数中运行,它就代表哪一个函数. 一般用在匿名函数中. 在匿名函数中有时会需要自己调用自己,但是由于是匿名函数,没有名子,无名可调. 这时就可以用argume ...

  7. kohana导入和导出

    一.导入 ini_set('memory_limit', '512M'); require_once(Kohana::find_file('vendor', 'PHPExcel/PHPExcel/IO ...

  8. WCF开发实战系列二:使用IIS发布WCF服务 转

    转 http://www.cnblogs.com/poissonnotes/archive/2010/08/28/1811141.html 上一篇中,我们创建了一个简单的WCF服务,在测试的时候,我们 ...

  9. Oracle 数据库中查看表空间的2种方法

    在Oracle数据库中查看表空间使用状况是我们在实际应用中经常涉及到的,以下的内容就就是对Oracle 数据库中查看表空间使用状况时所要用到的SQL的描述,希望你能从中获得自己想要的东西. Oracl ...

  10. Shiro集成web环境[Springboot]-基础使用

    Shiro集成web环境[Springboot] 1.shiro官网查找依赖的jar,其中shiro-ehcache做授权缓存时使用,另外还需要导入ehcache的jar包 <dependenc ...