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. 参考hadoop

    参考hadoop http://blog.itpub.net/26613085/

  2. Confluence 6 让一个空间可以公众访问

    如果你希望将一个空间分享给没有登录 Confluence 的用户(匿名用户)可以访问的话,你需要将这个空间标记为 公开(public).  让一个空间可以公开的访问的话,你就不能选择如何对这个空间进行 ...

  3. python and or的理解规则

    >>> 'a' and 'b' 'b' >>> '' and 'b' '' >>> 'a' and 'b' and 'c' 'c’ 解释:在布尔上 ...

  4. 20165309 实验二 Java面向对象程序设计

    2017-2018-2 20165309实验二<Java面向对象程序设计>实验报告 一.实验内容 1. 初步掌握单元测试和TDD 2. 理解并掌握面向对象三要素:封装.继承.多态 3. 初 ...

  5. HTTP的连接过程

    一.HTTP通信机制是在一次完整的HTTP通信过程中,Web浏览器与Web服务器之间将完成下列7个步骤: 1.域名解析 2.发起TCP的3次握手 3. Web浏览器向Web服务器发送http请求命令  ...

  6. ALV打印模板(存代码)

    *&---------------------------------------------------------------------* *& Report ZMMF013 * ...

  7. ADO.NET json数组多条记录执行在DAL层循环(执行存储过程)

    public int UpdateRegdate(tj_book_patient regdatejson) { int temp; SqlParameter[] ps = new SqlParamet ...

  8. 解决PLSQL Developer 插入中文 乱码问题(转)

    原文地址:解决PLSQL Developer 插入中文 乱码问题 PLSQL Developer 插入中文 乱码问题,如图     这个是由于oracle服务器端字符编码 和 Oracle 客户端 字 ...

  9. const 内联 枚举 宏

    const 常量   程序运行时在常量表中,系统为它分配内存,在堆栈分配了空间:const常量有数据类型:语句末有分号:有类型检查:可以限制范围 //将所有不希望改变的变量加const修饰 const ...

  10. “reliable message”事件引发的思考

    今天无意间看到了“reliable message"事件,平时还真没深入研究过这个事件,于是,就收集资料并稍微研究了一下,以下是官方就该事件给出的说明: When you send a me ...