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. TP5中的小知识

    在TP5中如果想用select 查询后,变成数组,用toArray()这个函数的话,必须在连接数据库中把 数据集返回类型变成 'resultset_type'=>'\think\Collecti ...

  2. 【洛谷p2837】晚餐队列安排

    (一定要先贴一下wz大佬对这道题的定位:) 另外说一句:我终于在拖了nnnnnnnnn天之后做完了这道题 算法标签:(其实也用不到辽上面都有)但我就是要贴一下咬我啊) 好啦好啦,上 思路: 首先为了节 ...

  3. python基础之lambda,sort,filter,map,递归函数的运用

    内容梗概:1. lamda 匿名函数2. sorted()3. filter()4. map()5. 递归函数 1.lambda 形式: lambda 参数:返回值 f = lambda x,y: x ...

  4. Bulb Switcher (leetcode java)

    问题描述: There are n bulbs that are initially off. You first turn on all the bulbs. Then, you turn off ...

  5. 女性睾酮水平高(High Testosterone Levels in Women)

    在外国网站了解睾酮高的一些资料,顺便记录生活点滴. 摘自网址:https://www.healthline.com/health/high-testosterone-in-women 高睾酮的妇女 睾 ...

  6. 漏洞复现——tomcat远程代码执行漏洞

    漏洞描述: 当存在该漏洞的Tomcat 运行在 Windows 主机上,且启用了 HTTP PUT请求方法,攻击者可通过构造的攻击请求向服务器上传包含任意代码的 JSP 文件,造成任意代码执行 影响范 ...

  7. windows下进程间通信与线程间通信

    进程间通信: 1.文件映射(Memory-Mapped Files) 文件映射(Memory-Mapped Files)能使进程把文件内容当作进程地址区间一块内存那样来对待.因此,进程不必使用文件I/ ...

  8. bool类型为什么可以当做int

    实际上bool型变量占用了一个字节的内存,当值为false的时候,实际存储的是0x00,为true时实际存储的是0x01,因此可以作为int整型使用 bool型只分0与非0,0为false,其余的包括 ...

  9. Qt中漂亮的几款QSS

    /* === Shared === */QStackedWidget, QLabel, QPushButton, QRadioButton, QCheckBox, QGroupBox, QStatus ...

  10. iperf测试工具

    一.iperf工具安装: 1.获取iperf源码安装包(iperf-3.0.5.tar.gz) 2.将iperf安装包上传到服务器/tmp/目录并解压 [root@localhost /]#cd /t ...